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