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>
42#include <optional>
43#include <algorithm>
45#include <pcb_track.h>
46#include <tool/tool_manager.h>
48#include <random>
49#include <core/profile.h>
50#include <wx/log.h>
51#include <pgm_base.h>
52
53
54#define MULTICHANNEL_EXTRA_DEBUG
55
56static const wxString traceMultichannelTool = wxT( "MULTICHANNEL_TOOL" );
57
58
60{
61}
62
63
65{
66
67}
68
69
71{
74}
75
76
78 std::set<FOOTPRINT*>& aComponents )
79{
81 PCBEXPR_UCODE ucode;
82 PCBEXPR_CONTEXT ctx, preflightCtx;
83
84 auto reportError = [&]( const wxString& aMessage, int aOffset )
85 {
86 wxLogTrace( traceMultichannelTool, wxT( "ERROR: %s"), aMessage );
87 };
88
89 ctx.SetErrorCallback( reportError );
90 preflightCtx.SetErrorCallback( reportError );
91 compiler.SetErrorCallback( reportError );
92 //compiler.SetDebugReporter( m_reporter );
93
94 wxLogTrace( traceMultichannelTool, wxT( "rule area '%s'"), aRuleArea->GetZoneName() );
95
96 wxString ruleText;
97
98 switch( aRuleArea->GetRuleAreaPlacementSourceType() )
99 {
100 case RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME:
101 {
102 ruleText = wxT( "A.memberOfSheetOrChildren('" ) + aRuleArea->GetRuleAreaPlacementSource()
103 + wxT( "')" );
104 break;
105 }
106 case RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS:
107 ruleText = wxT( "A.hasComponentClass('" ) + aRuleArea->GetRuleAreaPlacementSource()
108 + wxT( "')" );
109 break;
110 case RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP_PLACEMENT:
111 ruleText = wxT( "A.memberOfGroup('" ) + aRuleArea->GetRuleAreaPlacementSource() + wxT( "')" );
112 break;
113 }
114
115 auto ok = compiler.Compile( ruleText, &ucode, &preflightCtx );
116
117 if( !ok )
118 {
119 return false;
120 }
121
122 for( FOOTPRINT* fp : board()->Footprints() )
123 {
124 ctx.SetItems( fp, fp );
125 auto val = ucode.Run( &ctx );
126 if( val->AsDouble() != 0.0 )
127 {
128 wxLogTrace( traceMultichannelTool, wxT( " - %s [sheet %s]" ), fp->GetReference(),
129 fp->GetSheetname() );
130
131 aComponents.insert( fp );
132 }
133 }
134
135 return true;
136}
137
138
139bool MULTICHANNEL_TOOL::findOtherItemsInRuleArea( ZONE* aRuleArea, std::set<BOARD_ITEM*>& aItems )
140{
141 std::vector<BOARD_ITEM*> result;
142
144 PCBEXPR_UCODE ucode;
145 PCBEXPR_CONTEXT ctx, preflightCtx;
146
147 auto reportError = [&]( const wxString& aMessage, int aOffset )
148 {
149 wxLogTrace( traceMultichannelTool, wxT( "ERROR: %s"), aMessage );
150 };
151
152 ctx.SetErrorCallback( reportError );
153 preflightCtx.SetErrorCallback( reportError );
154 compiler.SetErrorCallback( reportError );
155
156 bool restoreBlankName = false;
157
158 if( aRuleArea->GetZoneName().IsEmpty() )
159 {
160 restoreBlankName = true;
161 aRuleArea->SetZoneName( aRuleArea->m_Uuid.AsString() );
162 }
163
164 wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ), aRuleArea->GetZoneName() );
165
166 if( !compiler.Compile( ruleText, &ucode, &preflightCtx ) )
167 {
168 if( restoreBlankName )
169 aRuleArea->SetZoneName( wxEmptyString );
170
171 return false;
172 }
173
174 auto testAndAdd =
175 [&]( BOARD_ITEM* aItem )
176 {
177 ctx.SetItems( aItem, aItem );
178 auto val = ucode.Run( &ctx );
179
180 if( val->AsDouble() != 0.0 )
181 aItems.insert( aItem );
182 };
183
184 for( ZONE* zone : board()->Zones() )
185 {
186 if( zone == aRuleArea )
187 continue;
188
189 testAndAdd( zone );
190 }
191
192 for( BOARD_ITEM* drawing : board()->Drawings() )
193 testAndAdd( drawing );
194
195 for( PCB_GROUP* group : board()->Groups() )
196 {
197 // A group is cloned in its entirety if *all* children are contained
198 bool addGroup = true;
199
200 group->RunOnChildren(
201 [&]( BOARD_ITEM* aItem )
202 {
203 if( aItem->IsType( { PCB_ZONE_T, PCB_SHAPE_T, PCB_DIMENSION_T } ) )
204 {
205 ctx.SetItems( aItem, aItem );
206 auto val = ucode.Run( &ctx );
207
208 if( val->AsDouble() == 0.0 )
209 addGroup = false;
210 }
211 },
212 RECURSE_MODE::RECURSE );
213
214 if( addGroup )
215 aItems.insert( group );
216 }
217
218 if( restoreBlankName )
219 aRuleArea->SetZoneName( wxEmptyString );
220
221 return true;
222}
223
224
225std::set<FOOTPRINT*> MULTICHANNEL_TOOL::queryComponentsInSheet( wxString aSheetName ) const
226{
227 std::set<FOOTPRINT*> rv;
228 if( aSheetName.EndsWith( wxT( "/" ) ) )
229 aSheetName.RemoveLast();
230
231 for( auto& fp : board()->Footprints() )
232 {
233 auto sn = fp->GetSheetname();
234 if( sn.EndsWith( wxT( "/" ) ) )
235 sn.RemoveLast();
236
237 if( sn == aSheetName )
238 {
239 rv.insert( fp );
240 }
241 }
242
243 return rv;
244}
245
246
247std::set<FOOTPRINT*>
248MULTICHANNEL_TOOL::queryComponentsInComponentClass( const wxString& aComponentClassName ) const
249{
250 std::set<FOOTPRINT*> rv;
251
252 for( auto& fp : board()->Footprints() )
253 {
254 if( fp->GetComponentClass()->ContainsClassName( aComponentClassName ) )
255 rv.insert( fp );
256 }
257
258 return rv;
259}
260
261
262std::set<FOOTPRINT*>
263MULTICHANNEL_TOOL::queryComponentsInGroup( const wxString& aGroupName ) const
264{
265 std::set<FOOTPRINT*> rv;
266
267 for( auto& group : board()->Groups() )
268 {
269 if( group->GetName() == aGroupName )
270 {
271 for( EDA_ITEM* item : group->GetItems() )
272 {
273 if( item->Type() == PCB_FOOTPRINT_T )
274 rv.insert( static_cast<FOOTPRINT*>( item ) );
275 }
276 }
277 }
278
279 return rv;
280}
281
282
283const SHAPE_LINE_CHAIN MULTICHANNEL_TOOL::buildRAOutline( std::set<FOOTPRINT*>& aFootprints,
284 int aMargin )
285{
286 std::vector<VECTOR2I> bbCorners;
287 bbCorners.reserve( aFootprints.size() * 4 );
288
289 for( auto fp : aFootprints )
290 {
291 const BOX2I bb = fp->GetBoundingBox( false ).GetInflated( aMargin );
292 KIGEOM::CollectBoxCorners( bb, bbCorners );
293 }
294
295 std::vector<VECTOR2I> hullVertices;
296 BuildConvexHull( hullVertices, bbCorners );
297
298 SHAPE_LINE_CHAIN hull( hullVertices );
299
300 // Make the newly computed convex hull use only 90 degree segments
301 return KIGEOM::RectifyPolygon( hull );
302}
303
304
306{
307 using PathAndName = std::pair<wxString, wxString>;
308 std::set<PathAndName> uniqueSheets;
309 std::set<wxString> uniqueComponentClasses;
310 std::set<wxString> uniqueGroups;
311
312 m_areas.m_areas.clear();
313
314 for( const FOOTPRINT* fp : board()->Footprints() )
315 {
316 uniqueSheets.insert( PathAndName( fp->GetSheetname(), fp->GetSheetfile() ) );
317
318 const COMPONENT_CLASS* compClass = fp->GetComponentClass();
319
320 for( const COMPONENT_CLASS* singleClass : compClass->GetConstituentClasses() )
321 uniqueComponentClasses.insert( singleClass->GetName() );
322
323 if( fp->GetParentGroup() && !fp->GetParentGroup()->GetName().IsEmpty() )
324 uniqueGroups.insert( fp->GetParentGroup()->GetName() );
325 }
326
327 for( const PathAndName& sheet : uniqueSheets )
328 {
329 RULE_AREA ent;
330
331 ent.m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME;
332 ent.m_generateEnabled = false;
333 ent.m_sheetPath = sheet.first;
334 ent.m_sheetName = sheet.second;
336 m_areas.m_areas.push_back( ent );
337
338 wxLogTrace( traceMultichannelTool, wxT("found sheet '%s' @ '%s' s %d\n"),
339 ent.m_sheetName, ent.m_sheetPath, (int)m_areas.m_areas.size() );
340 }
341
342 for( const wxString& compClass : uniqueComponentClasses )
343 {
344 RULE_AREA ent;
345
346 ent.m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS;
347 ent.m_generateEnabled = false;
348 ent.m_componentClass = compClass;
350 m_areas.m_areas.push_back( ent );
351
352 wxLogTrace( traceMultichannelTool, wxT( "found component class '%s' s %d\n" ),
353 ent.m_componentClass, static_cast<int>( m_areas.m_areas.size() ) );
354 }
355
356 for( const wxString& groupName : uniqueGroups )
357 {
358 RULE_AREA ent;
359
360 ent.m_sourceType = RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP_PLACEMENT;
361 ent.m_generateEnabled = false;
362 ent.m_groupName = groupName;
364 m_areas.m_areas.push_back( ent );
365
366 wxLogTrace( traceMultichannelTool, wxT( "found group '%s' s %d\n" ),
367 ent.m_componentClass, static_cast<int>( m_areas.m_areas.size() ) );
368 }
369}
370
371
373{
374 m_areas.m_areas.clear();
375
376 for( ZONE* zone : board()->Zones() )
377 {
378 if( !zone->GetIsRuleArea() )
379 continue;
380 if( !zone->GetRuleAreaPlacementEnabled() )
381 continue;
382
383 RULE_AREA area;
384
385 area.m_existsAlready = true;
386 area.m_area = zone;
387
389
390 area.m_ruleName = zone->GetZoneName();
391 area.m_center = zone->Outline()->COutline( 0 ).Centre();
392 m_areas.m_areas.push_back( area );
393
394 wxLogTrace( traceMultichannelTool, wxT("RA '%s', %d footprints\n"), area.m_ruleName, (int) area.m_raFootprints.size() );
395 }
396
397 wxLogTrace( traceMultichannelTool, wxT("Total RAs found: %d\n"), (int) m_areas.m_areas.size() );
398}
399
400
402{
403 for( RULE_AREA& ra : m_areas.m_areas )
404 {
405 if( ra.m_ruleName == aName )
406 return &ra;
407 }
408
409 return nullptr;
410}
411
412
414{
416}
417
418
420{
421 std::vector<ZONE*> refRAs;
422
423 auto isSelectedItemAnRA = []( EDA_ITEM* aItem ) -> ZONE*
424 {
425 if( !aItem || aItem->Type() != PCB_ZONE_T )
426 return nullptr;
427
428 ZONE* zone = static_cast<ZONE*>( aItem );
429
430 if( !zone->GetIsRuleArea() )
431 return nullptr;
432
433 if( !zone->GetRuleAreaPlacementEnabled() )
434 return nullptr;
435
436 return zone;
437 };
438
439 for( EDA_ITEM* item : selection() )
440 {
441 if( auto zone = isSelectedItemAnRA( item ) )
442 {
443 refRAs.push_back(zone);
444 }
445 else if ( item->Type() == PCB_GROUP_T )
446 {
447 PCB_GROUP *group = static_cast<PCB_GROUP*>( item );
448
449 for( EDA_ITEM* grpItem : group->GetItems() )
450 {
451 if( auto grpZone = isSelectedItemAnRA( grpItem ) )
452 {
453 refRAs.push_back( grpZone );
454 }
455 }
456 }
457 }
458
459 if( refRAs.size() != 1 )
460 {
463 this,
464 _( "Select a reference Rule Area to copy from..." ),
465 [&]( EDA_ITEM* aItem )
466 {
467 return isSelectedItemAnRA( aItem ) != nullptr;
468 }
469 } );
470
471 return 0;
472 }
473
475
476 int status = CheckRACompatibility( refRAs.front() );
477
478 if( status < 0 )
479 return status;
480
481 if( m_areas.m_areas.size() <= 1 )
482 {
483 frame()->ShowInfoBarError( _( "No Rule Areas to repeat layout to have been found." ),
484 true );
485 return 0;
486 }
487
489 int ret = dialog.ShowModal();
490
491 if( ret != wxID_OK )
492 return 0;
493
494 return RepeatLayout( aEvent, refRAs.front() );
495}
496
497
499{
500 m_areas.m_refRA = nullptr;
501
502 for( RULE_AREA& ra : m_areas.m_areas )
503 {
504 if( ra.m_area == aRefZone )
505 {
506 m_areas.m_refRA = &ra;
507 break;
508 }
509 }
510
511 if( !m_areas.m_refRA )
512 return -1;
513
514 m_areas.m_compatMap.clear();
515
516 for( RULE_AREA& ra : m_areas.m_areas )
517 {
518 if( ra.m_area == m_areas.m_refRA->m_area )
519 continue;
520
522
524 }
525
526 return 0;
527}
528
529
530int MULTICHANNEL_TOOL::RepeatLayout( const TOOL_EVENT& aEvent, ZONE* aRefZone )
531{
532 int totalCopied = 0;
533
534 BOARD_COMMIT commit( GetManager(), true );
535
536 for( auto& targetArea : m_areas.m_compatMap )
537 {
538 if( !targetArea.second.m_doCopy )
539 {
540 wxLogTrace( traceMultichannelTool, wxT("skipping copy to RA '%s' (disabled in dialog)\n"),
541 targetArea.first->m_ruleName );
542 continue;
543 }
544
545 if( !targetArea.second.m_isOk )
546 continue;
547
548
549 if( !copyRuleAreaContents( targetArea.second.m_matchingComponents, &commit, m_areas.m_refRA,
550 targetArea.first, m_areas.m_options, targetArea.second.m_affectedItems,
551 targetArea.second.m_groupableItems ) )
552 {
553 auto errMsg = wxString::Format(
554 _( "Copy Rule Area contents failed between rule areas '%s' and '%s'." ),
556 targetArea.first->m_area->GetZoneName() );
557
558 commit.Revert();
559
560 if( Pgm().IsGUI() )
561 {
562 frame()->ShowInfoBarError( errMsg, true );
563 }
564
565 return -1;
566 }
567 totalCopied++;
568 }
569
570
571 commit.Push( _( "Repeat layout" ) );
572
574 {
575 BOARD_COMMIT grpCommit( GetManager(), true );
576
577 for( auto& targetArea : m_areas.m_compatMap )
578 {
579 pruneExistingGroups( grpCommit, targetArea.second.m_affectedItems );
580
581 PCB_GROUP* grp = new PCB_GROUP( board() );
582
583 grpCommit.Add( grp );
584
585 for( BOARD_ITEM* item : targetArea.second.m_groupableItems )
586 {
587 grpCommit.Stage( item, CHT_GROUP );
588 }
589 }
590
591 grpCommit.Push( _( "Group repeated items" ) );
592 }
593
594
595 if( Pgm().IsGUI() )
596 {
597 frame()->ShowInfoBarMsg( wxString::Format( _( "Copied to %d Rule Areas." ), totalCopied ),
598 true );
599 }
600 return 0;
601}
602
603
604wxString MULTICHANNEL_TOOL::stripComponentIndex( const wxString& aRef ) const
605{
606 wxString rv;
607
608 // fixme: i'm pretty sure this can be written in a simpler way, but I really suck at figuring
609 // out which wx's built in functions would do it for me. And I hate regexps :-)
610 for( auto k : aRef )
611 {
612 if( !k.IsAscii() )
613 break;
614 char c;
615 k.GetAsChar( &c );
616
617 if( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c == '_' ) )
618 rv.Append( k );
619 else
620 break;
621 }
622
623 return rv;
624}
625
626
627int MULTICHANNEL_TOOL::findRoutedConnections( std::set<BOARD_ITEM*>& aOutput,
628 std::shared_ptr<CONNECTIVITY_DATA> aConnectivity,
629 const SHAPE_POLY_SET& aRAPoly,
630 RULE_AREA* aRA,
631 FOOTPRINT* aFp,
632 const REPEAT_LAYOUT_OPTIONS& aOpts ) const
633{
634 std::set<BOARD_ITEM*> conns;
635
636 for( PAD* pad : aFp->Pads() )
637 {
638 auto connectedItems = aConnectivity->GetConnectedItems( pad, EXCLUDE_ZONES | IGNORE_NETS );
639
640 for( BOARD_CONNECTED_ITEM* item : connectedItems )
641 conns.insert( item );
642 }
643
644 int count = 0;
645
646 for( BOARD_ITEM* item : conns )
647 {
648 // fixme: respect layer sets assigned to each RA
649
650 if( item->Type() == PCB_PAD_T )
651 continue;
652
653 std::shared_ptr<SHAPE> effShape = item->GetEffectiveShape( item->GetLayer() );
654
655 if( effShape->Collide( &aRAPoly, 0 ) )
656 {
657 aOutput.insert( item );
658 count++;
659 }
660 }
661
662 // The user also will consider tracks and vias that are inside the source area but
663 // not connected to any of the source pads to count as "routing" (e.g. stitching vias)
664
666 PCBEXPR_UCODE ucode;
667 PCBEXPR_CONTEXT ctx, preflightCtx;
668
669 auto reportError = [&]( const wxString& aMessage, int aOffset )
670 {
671 wxLogTrace( traceMultichannelTool, wxT( "ERROR: %s"), aMessage );
672 };
673
674 ctx.SetErrorCallback( reportError );
675 preflightCtx.SetErrorCallback( reportError );
676 compiler.SetErrorCallback( reportError );
677
678 bool restoreBlankName = false;
679
680 if( aRA->m_area->GetZoneName().IsEmpty() )
681 {
682 restoreBlankName = true;
683 aRA->m_area->SetZoneName( aRA->m_area->m_Uuid.AsString() );
684 }
685
686 wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ),
687 aRA->m_area->GetZoneName() );
688
689 auto testAndAdd =
690 [&]( BOARD_ITEM* aItem )
691 {
692 if( aOutput.contains( aItem ) )
693 return;
694
695 ctx.SetItems( aItem, aItem );
696 auto val = ucode.Run( &ctx );
697
698 if( val->AsDouble() != 0.0 )
699 {
700 aOutput.insert( aItem );
701 count++;
702 }
703 };
704
705 if( compiler.Compile( ruleText, &ucode, &preflightCtx ) )
706 {
707 for( PCB_TRACK* track : board()->Tracks() )
708 testAndAdd( track );
709 }
710
711 if( restoreBlankName )
712 aRA->m_area->SetZoneName( wxEmptyString );
713
714 return count;
715}
716
717
719 BOARD_COMMIT* aCommit,
720 RULE_AREA* aRefArea, RULE_AREA* aTargetArea,
722 std::unordered_set<BOARD_ITEM*>& aAffectedItems,
723 std::unordered_set<BOARD_ITEM*>& aGroupableItems )
724{
725 // copy RA shapes first
726 SHAPE_LINE_CHAIN refOutline = aRefArea->m_area->Outline()->COutline( 0 );
727 SHAPE_LINE_CHAIN targetOutline = aTargetArea->m_area->Outline()->COutline( 0 );
728
729 VECTOR2I disp = aTargetArea->m_center - aRefArea->m_center;
730
731 SHAPE_POLY_SET refPoly;
732 refPoly.AddOutline( refOutline );
733 refPoly.CacheTriangulation( false );
734
735 SHAPE_POLY_SET targetPoly;
736
737 SHAPE_LINE_CHAIN newTargetOutline( refOutline );
738 newTargetOutline.Move( disp );
739 targetPoly.AddOutline( newTargetOutline );
740 targetPoly.CacheTriangulation( false );
741
742 auto connectivity = board()->GetConnectivity();
743
744 aCommit->Modify( aTargetArea->m_area );
745
746 aAffectedItems.insert( aTargetArea->m_area );
747 aGroupableItems.insert( aTargetArea->m_area );
748
749 if( aOpts.m_copyRouting )
750 {
751 std::set<BOARD_ITEM*> refRouting;
752 std::set<BOARD_ITEM*> targetRouting;
753
754 wxLogTrace( traceMultichannelTool, wxT("copying routing: %d fps\n"), (int) aMatches.size() );
755
756 for( auto& fpPair : aMatches )
757 {
758 findRoutedConnections( targetRouting, connectivity, targetPoly, aTargetArea,
759 fpPair.second, aOpts );
760 findRoutedConnections( refRouting, connectivity, refPoly, aRefArea, fpPair.first,
761 aOpts );
762
763 wxLogTrace( traceMultichannelTool, wxT("target-routes %d\n"), (int) targetRouting.size() );
764 }
765
766 for( BOARD_ITEM* item : targetRouting )
767 {
768 if( item->IsLocked() && !aOpts.m_includeLockedItems )
769 continue;
770
771 // item already removed
772 if( aCommit->GetStatus( item ) != 0 )
773 continue;
774
775 if( aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
776 {
777 aAffectedItems.insert( item );
778 aCommit->Remove( item );
779 }
780 }
781
782 for( BOARD_ITEM* item : refRouting )
783 {
784 if( !aRefArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
785 continue;
786
787 if( !aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
788 continue;
789
790 BOARD_ITEM* copied = static_cast<BOARD_ITEM*>( item->Clone() );
791
792 if( item->Type() == PCB_VIA_T )
793 {
794 fixupNet( static_cast<BOARD_CONNECTED_ITEM*>( item ), static_cast<BOARD_CONNECTED_ITEM*>( copied ),
795 aMatches );
796 }
797 copied->Move( disp );
798 copied->SetParentGroup( nullptr );
799 const_cast<KIID&>( copied->m_Uuid ) = KIID();
800 aGroupableItems.insert( copied );
801 aCommit->Add( copied );
802 }
803 }
804
805 if( aOpts.m_copyOtherItems )
806 {
807 std::set<BOARD_ITEM*> sourceItems;
808 std::set<BOARD_ITEM*> targetItems;
809
810 findOtherItemsInRuleArea( aRefArea->m_area, sourceItems );
811 findOtherItemsInRuleArea( aTargetArea->m_area, targetItems );
812
813 for( BOARD_ITEM* item : targetItems )
814 {
815 if( item->Type() == PCB_TEXT_T && item->GetParent()
816 && item->GetParent()->Type() == PCB_FOOTPRINT_T )
817 continue;
818
819 if( item->IsLocked() && !aOpts.m_includeLockedItems )
820 continue;
821
822 // item already removed
823 if( aCommit->GetStatus( item ) != 0 )
824 continue;
825
826 if( item->Type() != PCB_ZONE_T )
827 {
828 if( aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
829 {
830 aAffectedItems.insert( item );
831 aCommit->Remove( item );
832 }
833 }
834 else
835 {
836 ZONE* zone = static_cast<ZONE*>( item );
837
838 // Check all zone layers are included in the rule area
839 bool layerMismatch = false;
840 LSET zoneLayers = zone->GetLayerSet();
841
842 for( const PCB_LAYER_ID& layer : zoneLayers )
843 {
844 if( !aTargetArea->m_area->GetLayerSet().Contains( layer ) )
845 layerMismatch = true;
846 }
847
848 if( !layerMismatch )
849 {
850 aAffectedItems.insert( zone );
851 aCommit->Remove( zone );
852 }
853 }
854 }
855
856 for( BOARD_ITEM* item : sourceItems )
857 {
858 if( item->Type() == PCB_TEXT_T && item->GetParent()
859 && item->GetParent()->Type() == PCB_FOOTPRINT_T )
860 continue;
861
862 BOARD_ITEM* copied = nullptr;
863
864 if( item->Type() != PCB_ZONE_T )
865 {
866 if( !aRefArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
867 continue;
868 if( !aTargetArea->m_area->GetLayerSet().Contains( item->GetLayer() ) )
869 continue;
870
871 if( item->Type() == PCB_GROUP_T )
872 {
873 copied = static_cast<PCB_GROUP*>( item )->DeepClone();
874 }
875 else
876 {
877 copied = static_cast<BOARD_ITEM*>( item->Clone() );
878 }
879 }
880 else
881 {
882 ZONE* zone = static_cast<ZONE*>( item );
883
884 // Check all zone layers are included in the rule area
885 bool layerMismatch = false;
886 LSET zoneLayers = zone->GetLayerSet();
887
888 for( const PCB_LAYER_ID& layer : zoneLayers )
889 {
890 if( !aRefArea->m_area->GetLayerSet().Contains( layer )
891 || !aTargetArea->m_area->GetLayerSet().Contains( layer ) )
892 {
893 layerMismatch = true;
894 }
895 }
896
897 if( layerMismatch )
898 continue;
899
900 ZONE* targetZone = static_cast<ZONE*>( item->Clone() );
901 fixupNet( zone, targetZone, aMatches );
902
903 copied = targetZone;
904 }
905
906 if( copied )
907 {
908 copied->ClearFlags();
909 copied->SetParentGroup( nullptr );
910 const_cast<KIID&>( copied->m_Uuid ) = KIID();
911 copied->Move( disp );
912 aGroupableItems.insert( copied );
913 aCommit->Add( copied );
914 }
915 }
916 }
917
918 aTargetArea->m_area->RemoveAllContours();
919 aTargetArea->m_area->AddPolygon( newTargetOutline );
920 aTargetArea->m_area->UnHatchBorder();
921 aTargetArea->m_area->HatchBorder();
922
923 if( aOpts.m_copyPlacement )
924 {
925 for( auto& fpPair : aMatches )
926 {
927 FOOTPRINT* refFP = fpPair.first;
928 FOOTPRINT* targetFP = fpPair.second;
929
930 if( !aRefArea->m_area->GetLayerSet().Contains( refFP->GetLayer() ) )
931 {
932 wxLogTrace( traceMultichannelTool, wxT( "discard ref:%s (ref layer)\n" ),
933 refFP->GetReference() );
934 continue;
935 }
936 if( !aTargetArea->m_area->GetLayerSet().Contains( refFP->GetLayer() ) )
937 {
938 wxLogTrace( traceMultichannelTool, wxT( "discard ref:%s (target layer)\n" ),
939 refFP->GetReference() );
940 continue;
941 }
942
943 // Ignore footprints outside of the rule area
944 if( !refFP->GetEffectiveShape( refFP->GetLayer() )->Collide( &refPoly, 0 ) )
945 continue;
946
947 if( targetFP->IsLocked() && !aOpts.m_includeLockedItems )
948 continue;
949
950 aCommit->Modify( targetFP );
951
952 targetFP->SetLayerAndFlip( refFP->GetLayer() );
953 targetFP->SetOrientation( refFP->GetOrientation() );
954 VECTOR2I targetPos = refFP->GetPosition() + disp;
955 targetFP->SetPosition( targetPos );
956
957 for( PCB_FIELD* refField : refFP->GetFields() )
958 {
959 if( !refField->IsVisible() )
960 continue;
961
962 PCB_FIELD* targetField = targetFP->GetField( refField->GetName() );
963 wxCHECK2( targetField, continue );
964
965 targetField->SetAttributes( refField->GetAttributes() );
966 targetField->SetPosition( refField->GetPosition() + disp );
967 targetField->SetIsKnockout( refField->IsKnockout() );
968 }
969
970 aAffectedItems.insert( targetFP );
971 aGroupableItems.insert( targetFP );
972 }
973 }
974
975 return true;
976}
977
983 TMATCH::COMPONENT_MATCHES& aComponentMatches )
984{
985 auto connectivity = board()->GetConnectivity();
986 const std::vector<BOARD_CONNECTED_ITEM*> refConnectedPads =
987 connectivity->GetNetItems( aRef->GetNetCode(), { PCB_PAD_T } );
988
989 for( const BOARD_CONNECTED_ITEM* refConItem : refConnectedPads )
990 {
991 if( refConItem->Type() != PCB_PAD_T )
992 continue;
993
994 const PAD* refPad = static_cast<const PAD*>( refConItem );
995 FOOTPRINT* sourceFootprint = refPad->GetParentFootprint();
996
997 if( aComponentMatches.contains( sourceFootprint ) )
998 {
999 const FOOTPRINT* targetFootprint = aComponentMatches[sourceFootprint];
1000 std::vector<const PAD*> targetFpPads = targetFootprint->GetPads( refPad->GetNumber() );
1001
1002 if( !targetFpPads.empty() )
1003 {
1004 int targetNetCode = targetFpPads[0]->GetNet()->GetNetCode();
1005 aTarget->SetNetCode( targetNetCode );
1006
1007 break;
1008 }
1009 }
1010 }
1011}
1012
1013
1015 RULE_AREA_COMPAT_DATA& aMatches )
1016{
1017 using namespace TMATCH;
1018
1019 std::unique_ptr<CONNECTION_GRAPH> cgRef ( CONNECTION_GRAPH::BuildFromFootprintSet( aRefArea->m_raFootprints ) );
1020 std::unique_ptr<CONNECTION_GRAPH> cgTarget ( CONNECTION_GRAPH::BuildFromFootprintSet( aTargetArea->m_raFootprints ) );
1021
1022 auto status = cgRef->FindIsomorphism( cgTarget.get(), aMatches.m_matchingComponents );
1023
1024 switch( status )
1025 {
1026 case CONNECTION_GRAPH::ST_OK:
1027 aMatches.m_isOk = true;
1028 aMatches.m_errorMsg = _("OK");
1029 break;
1030 case CONNECTION_GRAPH::ST_EMPTY:
1031 aMatches.m_isOk = false;
1032 aMatches.m_errorMsg = _("One or both of the areas has no components assigned.");
1033 break;
1034 case CONNECTION_GRAPH::ST_COMPONENT_COUNT_MISMATCH:
1035 aMatches.m_isOk = false;
1036 aMatches.m_errorMsg = _("Component count mismatch");
1037 break;
1038 case CONNECTION_GRAPH::ST_ITERATION_COUNT_EXCEEDED:
1039 aMatches.m_isOk = false;
1040 aMatches.m_errorMsg = _("Iteration count exceeded (timeout)");
1041 break;
1042 case CONNECTION_GRAPH::ST_TOPOLOGY_MISMATCH:
1043 aMatches.m_isOk = false;
1044 aMatches.m_errorMsg = _("Topology mismatch");
1045 break;
1046 default:
1047 break;
1048 }
1049
1050 return ( status == TMATCH::CONNECTION_GRAPH::ST_OK );
1051}
1052
1053
1055 const std::unordered_set<BOARD_ITEM*>& aItemsToRemove )
1056{
1057 std::deque<PCB_GROUP*> pending ( board()->Groups() );
1058 while( !pending.empty() )
1059 {
1060 auto grp = pending.front();
1061 pending.pop_front();
1062
1063 std::unordered_set<EDA_ITEM*>& grpItems = grp->GetItems();
1064 size_t n_erased = 0;
1065
1066 for( EDA_ITEM* refItem : grpItems )
1067 {
1068 if( refItem->Type() == PCB_GROUP_T )
1069 pending.push_back( static_cast<PCB_GROUP*>(refItem) );
1070
1071 for( BOARD_ITEM* testItem : aItemsToRemove )
1072 {
1073 if( refItem->m_Uuid == testItem->m_Uuid )
1074 {
1075 aCommit.Stage( refItem, CHT_UNGROUP );
1076 n_erased++;
1077 }
1078 }
1079 }
1080
1081 if( n_erased == grpItems.size() )
1082 {
1083 aCommit.Stage( grp, CHT_REMOVE );
1084 }
1085
1086 }
1087
1088 return false;
1089}
1090
1091
1093{
1094 if( Pgm().IsGUI() )
1095 {
1097
1098 if( m_areas.m_areas.size() <= 1 )
1099 {
1100 frame()->ShowInfoBarError( _( "Cannot auto-generate any placement areas because the "
1101 "schematic has only one or no hierarchical sheet(s) or "
1102 "component classes." ),
1103 true );
1104 return 0;
1105 }
1106
1108 int ret = dialog.ShowModal();
1109
1110 if( ret != wxID_OK )
1111 return 0;
1112 }
1113
1114 for( ZONE* zone : board()->Zones() )
1115 {
1116 if( !zone->GetIsRuleArea() )
1117 continue;
1118 if( !zone->GetRuleAreaPlacementEnabled() )
1119 continue;
1120
1121 std::set<FOOTPRINT*> components;
1122 identifyComponentsInRuleArea( zone, components );
1123
1124 if( components.empty() )
1125 continue;
1126
1127 for( RULE_AREA& ra : m_areas.m_areas )
1128 {
1129 if( components == ra.m_components )
1130 {
1131 if( zone->GetRuleAreaPlacementSourceType()
1132 == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1133 {
1134 wxLogTrace(
1136 wxT( "Placement rule area for sheet '%s' already exists as '%s'\n" ),
1137 ra.m_sheetPath, zone->GetZoneName() );
1138 }
1139 else if( zone->GetRuleAreaPlacementSourceType()
1140 == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
1141 {
1142 wxLogTrace( traceMultichannelTool,
1143 wxT( "Placement rule area for component class '%s' already exists "
1144 "as '%s'\n" ),
1145 ra.m_componentClass, zone->GetZoneName() );
1146 }
1147 else
1148 {
1149 wxLogTrace( traceMultichannelTool,
1150 wxT( "Placement rule area for group '%s' already exists "
1151 "as '%s'\n" ),
1152 ra.m_groupName, zone->GetZoneName() );
1153 }
1154
1155 ra.m_oldArea = zone;
1156 ra.m_existsAlready = true;
1157 }
1158 }
1159 }
1160
1161 wxLogTrace( traceMultichannelTool,
1162 wxT( "%d placement areas found\n" ), (int) m_areas.m_areas.size() );
1163
1164 BOARD_COMMIT commit( GetManager(), true );
1165
1166 for( RULE_AREA& ra : m_areas.m_areas )
1167 {
1168 if( !ra.m_generateEnabled )
1169 continue;
1170
1172 continue;
1173
1174 if( ra.m_components.empty() )
1175 continue;
1176
1177 SHAPE_LINE_CHAIN raOutline = buildRAOutline( ra.m_components, 100000 );
1178
1179 std::unique_ptr<ZONE> newZone( new ZONE( board() ) );
1180
1181 if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1182 {
1183 newZone->SetZoneName(
1184 wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_sheetPath ) );
1185 }
1186 else if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
1187 {
1188 newZone->SetZoneName(
1189 wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_componentClass ) );
1190 }
1191 else
1192 {
1193 newZone->SetZoneName( wxString::Format( wxT( "auto-placement-area-%s" ), ra.m_groupName ) );
1194 }
1195
1196 wxLogTrace( traceMultichannelTool, wxT( "Generated rule area '%s' (%d components)\n" ),
1197 newZone->GetZoneName(), (int) ra.m_components.size() );
1198
1199 newZone->SetIsRuleArea( true );
1200 newZone->SetLayerSet( LSET::AllCuMask() );
1201 newZone->SetRuleAreaPlacementEnabled( true );
1202 newZone->SetDoNotAllowZoneFills( false );
1203 newZone->SetDoNotAllowVias( false );
1204 newZone->SetDoNotAllowTracks( false );
1205 newZone->SetDoNotAllowPads( false );
1206 newZone->SetDoNotAllowFootprints( false );
1207
1208 if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME )
1209 {
1210 newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::SHEETNAME );
1211 newZone->SetRuleAreaPlacementSource( ra.m_sheetPath );
1212 }
1213 else if( ra.m_sourceType == RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS )
1214 {
1215 newZone->SetRuleAreaPlacementSourceType(
1216 RULE_AREA_PLACEMENT_SOURCE_TYPE::COMPONENT_CLASS );
1217 newZone->SetRuleAreaPlacementSource( ra.m_componentClass );
1218 }
1219 else
1220 {
1221 newZone->SetRuleAreaPlacementSourceType( RULE_AREA_PLACEMENT_SOURCE_TYPE::GROUP_PLACEMENT );
1222 newZone->SetRuleAreaPlacementSource( ra.m_groupName );
1223 }
1224
1225 newZone->AddPolygon( raOutline );
1226 newZone->SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE::NO_HATCH );
1227
1228 if( ra.m_existsAlready )
1229 {
1230 commit.Remove( ra.m_oldArea );
1231 }
1232
1233 ra.m_area = newZone.get();
1234 commit.Add( newZone.release() );
1235 }
1236
1237 commit.Push( _( "Auto-generate placement rule areas" ) );
1238
1239 // fixme: handle corner cases where the items belonging to a Rule Area already
1240 // belong to other groups.
1241
1243 {
1244 // fixme: sth gets weird when creating new zones & grouping them within a single COMMIT
1245 BOARD_COMMIT grpCommit( GetManager(), true );
1246
1247 for( RULE_AREA& ra : m_areas.m_areas )
1248 {
1249 if( !ra.m_generateEnabled )
1250 continue;
1251
1253 continue;
1254
1255 std::unordered_set<BOARD_ITEM*> toPrune;
1256
1257 std::copy( ra.m_components.begin(), ra.m_components.end(),
1258 std::inserter( toPrune, toPrune.begin() ) );
1259
1260 if( ra.m_existsAlready )
1261 toPrune.insert( ra.m_area );
1262
1263 pruneExistingGroups( grpCommit, toPrune );
1264
1265 PCB_GROUP* grp = new PCB_GROUP( board() );
1266
1267 grpCommit.Add( grp );
1268 grpCommit.Stage( ra.m_area, CHT_GROUP );
1269
1270 for( FOOTPRINT* fp : ra.m_components )
1271 {
1272 grpCommit.Stage( fp, CHT_GROUP );
1273 }
1274 }
1275 grpCommit.Push( _( "Group components with their placement rule areas" ) );
1276 }
1277
1278 return true;
1279}
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:78
virtual void SetIsKnockout(bool aKnockout)
Definition: board_item.h:317
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:299
const ZONES & Zones() const
Definition: board.h:342
const TRACKS & Tracks() const
Definition: board.h:336
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:495
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:63
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:145
A lightweight representation of a component class.
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:96
const KIID m_Uuid
Definition: eda_item.h:502
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition: eda_item.h:188
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition: eda_text.cpp:433
void SetPosition(const VECTOR2I &aPos) override
Definition: footprint.cpp:2462
EDA_ANGLE GetOrientation() const
Definition: footprint.h:232
void SetOrientation(const EDA_ANGLE &aNewAngle)
Definition: footprint.cpp:2544
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:2957
PCB_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this footprint.
Definition: footprint.cpp:585
std::deque< PAD * > & Pads()
Definition: footprint.h:211
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:241
bool IsLocked() const override
Definition: footprint.h:416
void SetLayerAndFlip(PCB_LAYER_ID aLayer)
Used as Layer property setter – performs a flip if necessary to set the footprint layer.
Definition: footprint.cpp:2394
std::vector< const PAD * > GetPads(const wxString &aPadNumber, const PAD *aIgnore=nullptr) const
Definition: footprint.cpp:1994
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
Definition: footprint.cpp:630
const wxString & GetReference() const
Definition: footprint.h:621
VECTOR2I GetPosition() const override
Definition: footprint.h:229
Definition: kiid.h:49
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:583
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 fixupNet(BOARD_CONNECTED_ITEM *aRef, BOARD_CONNECTED_ITEM *aTarget, TMATCH::COMPONENT_MATCHES &aComponentMatches)
Attempts to modify the assigned net of copied items, especially intended for zones and vias.
std::set< FOOTPRINT * > queryComponentsInComponentClass(const wxString &aComponentClassName) const
RULE_AREA * findRAByName(const wxString &aName)
std::set< FOOTPRINT * > queryComponentsInGroup(const wxString &aGroupName) const
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:136
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
static TOOL_ACTION repeatLayout
Definition: pcb_actions.h:581
static TOOL_ACTION generatePlacementRuleAreas
Definition: pcb_actions.h:582
static TOOL_ACTION selectItemInteractively
Selection of reference points/items.
Definition: pcb_actions.h:305
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:53
virtual void SetPosition(const VECTOR2I &aPos) override
Definition: pcb_text.h:89
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:74
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:752
wxString GetRuleAreaPlacementSource() const
Definition: zone.h:757
void AddPolygon(std::vector< VECTOR2I > &aPolygon)
Add a polygon to the zone outline.
Definition: zone.cpp:1108
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:1258
bool GetRuleAreaPlacementEnabled() const
Definition: zone.h:754
SHAPE_POLY_SET * Outline()
Definition: zone.h:368
const wxString & GetZoneName() const
Definition: zone.h:163
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.h:136
RULE_AREA_PLACEMENT_SOURCE_TYPE GetRuleAreaPlacementSourceType() const
Definition: zone.h:759
void SetZoneName(const wxString &aName)
Definition: zone.h:164
void UnHatchBorder()
Clear the zone's hatch.
Definition: zone.cpp:1252
void RemoveAllContours(void)
Definition: zone.h:582
@ CHT_GROUP
Definition: commit.h:45
@ CHT_REMOVE
Definition: commit.h:43
@ CHT_UNGROUP
Definition: commit.h:46
#define EXCLUDE_ZONES
#define IGNORE_NETS
Function GetConnectedItems() Returns a list of items connected to a source item aItem.
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:1071
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_groupName
wxString m_sheetPath
bool m_generateEnabled
bool copied
@ 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