KiCad PCB EDA Suite
pad_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 (C) 2017-2022 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 "pad_tool.h"
26#include "pcb_painter.h"
27#include <macros.h>
29#include <view/view_controls.h>
30#include <tool/tool_manager.h>
32#include <board_item.h>
33#include <footprint.h>
34#include <fp_shape.h>
35#include <pad.h>
36#include <pcbnew_settings.h>
37#include <board_commit.h>
39#include <tools/pcb_actions.h>
43#include <tools/edit_tool.h>
45#include <widgets/wx_infobar.h>
46
47
49
50
52 PCB_TOOL_BASE( "pcbnew.PadTool" ),
53 m_wasHighContrast( false ),
54 m_editPad( niluuid )
55{}
56
57
59{}
60
61
63{
64 if( aReason == MODEL_RELOAD )
65 m_lastPadNumber = wxT( "1" );
66
67 if( board() && board()->GetItem( m_editPad ) == DELETED_BOARD_ITEM::GetInstance() )
68 {
70 bool highContrast = ( opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
71
72 if( m_wasHighContrast != highContrast )
74
75 frame()->GetInfoBar()->Dismiss();
76
78 }
79}
80
81
83{
85
86 if( selTool )
87 {
88 // Add context menu entries that are displayed when selection tool is active
89 CONDITIONAL_MENU& menu = selTool->GetToolMenu().GetMenu();
90
94
95 auto explodeCondition =
96 [&]( const SELECTION& aSel )
97 {
98 return m_editPad == niluuid && aSel.Size() == 1 && aSel[0]->Type() == PCB_PAD_T;
99 };
100
101 auto recombineCondition =
102 [&]( const SELECTION& aSel )
103 {
104 return m_editPad != niluuid;
105 };
106
107 menu.AddSeparator( 400 );
108
110 {
112 menu.AddItem( PCB_ACTIONS::recombinePad, recombineCondition, 400 );
113 menu.AddItem( PCB_ACTIONS::explodePad, explodeCondition, 400 );
114 }
115
116 menu.AddItem( PCB_ACTIONS::copyPadSettings, singlePadSel, 400 );
117 menu.AddItem( PCB_ACTIONS::applyPadSettings, padSel, 400 );
118 menu.AddItem( PCB_ACTIONS::pushPadSettings, singlePadSel, 400 );
119 }
120
121 auto& ctxMenu = m_menu.GetMenu();
122
123 // cancel current tool goes in main context menu at the top if present
125 ctxMenu.AddSeparator( 1 );
126
133
134 // Finally, add the standard zoom/grid items
135 getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( m_menu );
136
137 return true;
138}
139
140
142{
144 const PCB_SELECTION& selection = selTool->GetSelection();
145 const PAD* masterPad = frame()->GetDesignSettings().m_Pad_Master.get();
146
147 BOARD_COMMIT commit( frame() );
148
149 // for every selected pad, paste global settings
150 for( EDA_ITEM* item : selection )
151 {
152 if( item->Type() == PCB_PAD_T )
153 {
154 commit.Modify( item );
155 static_cast<PAD&>( *item ).ImportSettingsFrom( *masterPad );
156 }
157 }
158
159 commit.Push( _( "Paste Pad Properties" ) );
160
162 frame()->Refresh();
163
164 return 0;
165}
166
167
169{
171 const PCB_SELECTION& selection = selTool->GetSelection();
172
173 // can only copy from a single pad
174 if( selection.Size() == 1 )
175 {
176 EDA_ITEM* item = selection[0];
177
178 if( item->Type() == PCB_PAD_T )
179 {
180 const PAD& selPad = static_cast<const PAD&>( *item );
181 frame()->GetDesignSettings().m_Pad_Master->ImportSettingsFrom( selPad );
182 }
183 }
184
185 return 0;
186}
187
188
189static void doPushPadProperties( BOARD& board, const PAD& aSrcPad, BOARD_COMMIT& commit,
190 bool aSameFootprints,
191 bool aPadShapeFilter,
192 bool aPadOrientFilter,
193 bool aPadLayerFilter,
194 bool aPadTypeFilter )
195{
196 const FOOTPRINT* refFootprint = aSrcPad.GetParent();
197
198 EDA_ANGLE srcPadAngle = aSrcPad.GetOrientation() - refFootprint->GetOrientation();
199
200 for( FOOTPRINT* footprint : board.Footprints() )
201 {
202 if( !aSameFootprints && ( footprint != refFootprint ) )
203 continue;
204
205 if( footprint->GetFPID() != refFootprint->GetFPID() )
206 continue;
207
208 for( PAD* pad : footprint->Pads() )
209 {
210 if( aPadShapeFilter && ( pad->GetShape() != aSrcPad.GetShape() ) )
211 continue;
212
213 EDA_ANGLE padAngle = pad->GetOrientation() - footprint->GetOrientation();
214
215 if( aPadOrientFilter && ( padAngle != srcPadAngle ) )
216 continue;
217
218 if( aPadLayerFilter && ( pad->GetLayerSet() != aSrcPad.GetLayerSet() ) )
219 continue;
220
221 if( aPadTypeFilter && ( pad->GetAttribute() != aSrcPad.GetAttribute() ) )
222 continue;
223
224 // Special-case for aperture pads
225 if( aPadTypeFilter && pad->GetAttribute() == PAD_ATTRIB::CONN )
226 {
227 if( pad->IsAperturePad() != aSrcPad.IsAperturePad() )
228 continue;
229 }
230
231 commit.Modify( pad );
232
233 // Apply source pad settings to this pad
234 pad->ImportSettingsFrom( aSrcPad );
235 }
236 }
237}
238
239
241{
243 const PCB_SELECTION& selection = selTool->GetSelection();
244 PAD* srcPad;
245
246 if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
247 srcPad = static_cast<PAD*>( selection[0] );
248 else
249 return 0;
250
251 FOOTPRINT* footprint = srcPad->GetParent();
252
253 if( !footprint )
254 return 0;
255
257
259 int dialogRet = dlg.ShowModal();
260
261 if( dialogRet == wxID_CANCEL )
262 return 0;
263
264 const bool edit_Same_Modules = (dialogRet == 1);
265
266 BOARD_COMMIT commit( frame() );
267
268 doPushPadProperties( *getModel<BOARD>(), *srcPad, commit, edit_Same_Modules,
273
274 commit.Push( _( "Push Pad Settings" ) );
275
277 frame()->Refresh();
278
279 return 0;
280}
281
282
284{
285 if( !board()->GetFirstFootprint() || board()->GetFirstFootprint()->Pads().empty() )
286 return 0;
287
288 GENERAL_COLLECTOR collector;
290 guide.SetIgnoreMTextsMarkedNoShow( true );
291 guide.SetIgnoreMTextsOnBack( true );
292 guide.SetIgnoreMTextsOnFront( true );
293 guide.SetIgnoreModulesVals( true );
294 guide.SetIgnoreModulesRefs( true );
295
296 DIALOG_ENUM_PADS settingsDlg( frame() );
297
298 if( settingsDlg.ShowModal() != wxID_OK )
299 return 0;
300
301 int seqPadNum = settingsDlg.GetStartNumber();
302 wxString padPrefix = settingsDlg.GetPrefix();
303 std::deque<int> storedPadNumbers;
304 std::map<wxString, std::pair<int, wxString>> oldNumbers;
305
307
308 frame()->PushTool( aEvent );
309
310 VECTOR2I oldCursorPos; // store the previous mouse cursor position, during mouse drag
311 std::list<PAD*> selectedPads;
312 BOARD_COMMIT commit( frame() );
313 bool isFirstPoint = true; // make sure oldCursorPos is initialized at least once
314 PADS pads = board()->GetFirstFootprint()->Pads();
315
316 MAGNETIC_SETTINGS mag_settings;
317 mag_settings.graphics = false;
318 mag_settings.tracks = MAGNETIC_OPTIONS::NO_EFFECT;
320 PCB_GRID_HELPER grid( m_toolMgr, &mag_settings );
321
322 grid.SetSnap( true );
323 grid.SetUseGrid( false );
324
325 auto setCursor =
326 [&]()
327 {
329 };
330
331 Activate();
332 // Must be done after Activate() so that it gets set into the correct context
333 getViewControls()->ShowCursor( true );
335 // Set initial cursor
336 setCursor();
337
338 STATUS_TEXT_POPUP statusPopup( frame() );
339 wxString msg = _( "Click on pad %s%d\nPress <esc> to cancel all; double-click to finish" );
340 statusPopup.SetText( wxString::Format( msg, padPrefix, seqPadNum ) );
341 statusPopup.Popup();
342 statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
343 canvas()->SetStatusPopup( statusPopup.GetPanel() );
344
345 while( TOOL_EVENT* evt = Wait() )
346 {
347 setCursor();
348
349 VECTOR2I cursorPos = grid.AlignToNearestPad( getViewControls()->GetMousePosition(), pads );
350 getViewControls()->ForceCursorPosition( true, cursorPos );
351
352 if( evt->IsCancelInteractive() )
353 {
355 commit.Revert();
356
357 frame()->PopTool( aEvent );
358 break;
359 }
360 else if( evt->IsActivate() )
361 {
362 commit.Push( _( "Renumber pads" ) );
363
364 frame()->PopTool( aEvent );
365 break;
366 }
367 else if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
368 {
369 selectedPads.clear();
370
371 // Be sure the old cursor mouse position was initialized:
372 if( isFirstPoint )
373 {
374 oldCursorPos = cursorPos;
375 isFirstPoint = false;
376 }
377
378 // wxWidgets deliver mouse move events not frequently enough, resulting in skipping
379 // pads if the user moves cursor too fast. To solve it, create a line that approximates
380 // the mouse move and search pads that are on the line.
381 int distance = ( cursorPos - oldCursorPos ).EuclideanNorm();
382 // Search will be made every 0.1 mm:
383 int segments = distance / int( 0.1 * pcbIUScale.IU_PER_MM ) + 1;
384 const VECTOR2I line_step( ( cursorPos - oldCursorPos ) / segments );
385
386 collector.Empty();
387
388 for( int j = 0; j < segments; ++j )
389 {
390 VECTOR2I testpoint( cursorPos.x - j * line_step.x, cursorPos.y - j * line_step.y );
391 collector.Collect( board(), { PCB_PAD_T }, testpoint, guide );
392
393 for( int i = 0; i < collector.GetCount(); ++i )
394 selectedPads.push_back( static_cast<PAD*>( collector[i] ) );
395 }
396
397 selectedPads.unique();
398
399 for( PAD* pad : selectedPads )
400 {
401 // If pad was not selected, then enumerate it
402 if( !pad->IsSelected() )
403 {
404 commit.Modify( pad );
405
406 // Rename pad and store the old name
407 int newval;
408
409 if( storedPadNumbers.size() > 0 )
410 {
411 newval = storedPadNumbers.front();
412 storedPadNumbers.pop_front();
413 }
414 else
415 newval = seqPadNum++;
416
417 wxString newNumber = wxString::Format( wxT( "%s%d" ), padPrefix, newval );
418 oldNumbers[newNumber] = { newval, pad->GetNumber() };
419 pad->SetNumber( newNumber );
420 SetLastPadNumber( newNumber );
421 pad->SetSelected();
422 getView()->Update( pad );
423
424 // Ensure the popup text shows the correct next value
425 if( storedPadNumbers.size() > 0 )
426 newval = storedPadNumbers.front();
427 else
428 newval = seqPadNum;
429
430 statusPopup.SetText( wxString::Format( msg, padPrefix, newval ) );
431 }
432
433 // ... or restore the old name if it was enumerated and clicked again
434 else if( pad->IsSelected() && evt->IsClick( BUT_LEFT ) )
435 {
436 auto it = oldNumbers.find( pad->GetNumber() );
437 wxASSERT( it != oldNumbers.end() );
438
439 if( it != oldNumbers.end() )
440 {
441 storedPadNumbers.push_back( it->second.first );
442 pad->SetNumber( it->second.second );
443 SetLastPadNumber( it->second.second );
444 oldNumbers.erase( it );
445
446 int newval = storedPadNumbers.front();
447
448 statusPopup.SetText( wxString::Format( msg, padPrefix, newval ) );
449 }
450
451 pad->ClearSelected();
452 getView()->Update( pad );
453 }
454 }
455 }
456 else if( evt->IsDblClick( BUT_LEFT ) )
457 {
458 commit.Push( _( "Renumber pads" ) );
459 frame()->PopTool( aEvent );
460 break;
461 }
462 else if( evt->IsClick( BUT_RIGHT ) )
463 {
465 }
466 else
467 {
468 evt->SetPassEvent();
469 }
470
471 // Prepare the next loop by updating the old cursor mouse position
472 // to this last mouse cursor position
473 oldCursorPos = getViewControls()->GetCursorPosition();
474 statusPopup.Move( wxGetMousePosition() + wxPoint( 20, 20 ) );
475 }
476
477 for( PAD* p : board()->GetFirstFootprint()->Pads() )
478 {
479 p->ClearSelected();
480 getView()->Update( p );
481 }
482
483 canvas()->SetStatusPopup( nullptr );
484 statusPopup.Hide();
485
488 return 0;
489}
490
491
492int PAD_TOOL::PlacePad( const TOOL_EVENT& aEvent )
493{
494 if( !board()->GetFirstFootprint() )
495 return 0;
496
497 struct PAD_PLACER : public INTERACTIVE_PLACER_BASE
498 {
499 PAD_PLACER( PAD_TOOL* aPadTool )
500 {
501 m_padTool = aPadTool;
502 }
503
504 virtual ~PAD_PLACER()
505 {
506 }
507
508 std::unique_ptr<BOARD_ITEM> CreateItem() override
509 {
510 PAD* pad = new PAD( m_board->GetFirstFootprint() );
511 PAD* master = m_frame->GetDesignSettings().m_Pad_Master.get();
512
513 pad->ImportSettingsFrom( *master );
514
515 // If the footprint type and master pad type directly conflict then make some
516 // adjustments. Otherwise assume the user set what they wanted.
517 if( ( m_board->GetFirstFootprint()->GetAttributes() & FP_SMD )
518 && master->GetAttribute() == PAD_ATTRIB::PTH )
519 {
520 pad->SetAttribute( PAD_ATTRIB::SMD );
521 pad->SetShape( PAD_SHAPE::ROUNDRECT );
522 pad->SetSizeX( 1.5 * pad->GetSizeY() );
523 pad->SetLayerSet( PAD::SMDMask() );
524 }
525 else if( ( m_board->GetFirstFootprint()->GetAttributes() & FP_THROUGH_HOLE )
526 && master->GetAttribute() == PAD_ATTRIB::SMD )
527 {
528 pad->SetAttribute( PAD_ATTRIB::PTH );
529 pad->SetShape( PAD_SHAPE::CIRCLE );
530 pad->SetSize( VECTOR2I( pad->GetSizeX(), pad->GetSizeX() ) );
531 pad->SetLayerSet( PAD::PTHMask() );
532 }
533
534 if( pad->CanHaveNumber() )
535 {
536 wxString padNumber = m_padTool->GetLastPadNumber();
537 padNumber = m_board->GetFirstFootprint()->GetNextPadNumber( padNumber );
538 pad->SetNumber( padNumber );
539 m_padTool->SetLastPadNumber( padNumber );
540 }
541
542 return std::unique_ptr<BOARD_ITEM>( pad );
543 }
544
545 bool PlaceItem( BOARD_ITEM *aItem, BOARD_COMMIT& aCommit ) override
546 {
547 PAD* pad = dynamic_cast<PAD*>( aItem );
548
549 if( pad )
550 {
551 m_frame->GetDesignSettings().m_Pad_Master->ImportSettingsFrom( *pad );
552 pad->SetLocalCoord();
553 aCommit.Add( aItem );
554 return true;
555 }
556
557 return false;
558 }
559
560 PAD_TOOL* m_padTool;
561 };
562
563 PAD_PLACER placer( this );
564
565 doInteractiveItemPlacement( aEvent, &placer, _( "Place pad" ),
567
568 return 0;
569}
570
571
572int PAD_TOOL::EditPad( const TOOL_EVENT& aEvent )
573{
575 PCB_RENDER_SETTINGS* settings = static_cast<PCB_RENDER_SETTINGS*>( view()->GetPainter()->GetSettings() );
576 WX_INFOBAR* infoBar = frame()->GetInfoBar();
578 wxString msg;
579
580 if( m_editPad != niluuid )
581 {
582 PAD* pad = dynamic_cast<PAD*>( frame()->GetItem( m_editPad ) );
583
584 if( pad )
585 {
586 BOARD_COMMIT commit( frame() );
587 RecombinePad( pad, false, commit );
588 commit.Push( _( "Recombine pad" ) );
589 }
590
592 }
593 else if( selection.Size() == 1 && selection[0]->Type() == PCB_PAD_T )
594 {
595 PAD* pad = static_cast<PAD*>( selection[0] );
596 PCB_LAYER_ID layer = explodePad( pad );
597
599 frame()->SetActiveLayer( layer );
600
601 settings->m_PadEditModePad = pad;
602
604 [&]( KIGFX::VIEW_ITEM* aItem ) -> bool
605 {
606 return dynamic_cast<PAD*>( aItem ) != nullptr;
607 } );
608
609 if( !m_wasHighContrast )
611
613 {
614 msg.Printf( _( "Pad Edit Mode. Press %s again to exit." ),
616 }
617 else
618 {
619 msg.Printf( _( "Pad Edit Mode. Press %s to exit." ),
621 }
622
623 infoBar->RemoveAllButtons();
624 infoBar->ShowMessage( msg, wxICON_INFORMATION );
625
626 m_editPad = pad->m_Uuid;
627 }
628
629 if( m_editPad == niluuid )
630 {
631 bool highContrast = ( opts.m_ContrastModeDisplay != HIGH_CONTRAST_MODE::NORMAL );
632
633 if( m_wasHighContrast != highContrast )
635
636 settings->m_PadEditModePad = nullptr;
637
638 // Note: KIGFX::REPAINT isn't enough for things that go from invisible to visible as
639 // they won't be found in the view layer's itemset for re-painting.
641 [&]( KIGFX::VIEW_ITEM* aItem ) -> bool
642 {
643 return dynamic_cast<PAD*>( aItem ) != nullptr;
644 } );
645
646 // Refresh now (otherwise there's an uncomfortably long pause while the infoBar
647 // closes before refresh).
648 canvas()->ForceRefresh();
649
650 infoBar->Dismiss();
651 }
652
653 return 0;
654}
655
656
658{
659 PCB_LAYER_ID layer;
660 BOARD_COMMIT commit( frame() );
661
662 if( aPad->IsOnLayer( F_Cu ) )
663 layer = F_Cu;
664 else if( aPad->IsOnLayer( B_Cu ) )
665 layer = B_Cu;
666 else
667 layer = *aPad->GetLayerSet().UIOrder();
668
669 if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
670 {
671 commit.Modify( aPad );
672
673 for( const std::shared_ptr<PCB_SHAPE>& primitive : aPad->GetPrimitives() )
674 {
675 FP_SHAPE* shape = new FP_SHAPE( board()->GetFirstFootprint() );
676
677 shape->SetShape( primitive->GetShape() );
678 shape->SetIsAnnotationProxy( primitive->IsAnnotationProxy());
679 shape->SetFilled( primitive->IsFilled() );
680 shape->SetStroke( primitive->GetStroke() );
681
682 switch( shape->GetShape() )
683 {
684 case SHAPE_T::SEGMENT:
685 case SHAPE_T::RECT:
686 case SHAPE_T::CIRCLE:
687 shape->SetStart( primitive->GetStart() );
688 shape->SetEnd( primitive->GetEnd() );
689 break;
690
691 case SHAPE_T::ARC:
692 shape->SetStart( primitive->GetStart() );
693 shape->SetEnd( primitive->GetEnd() );
694 shape->SetCenter( primitive->GetCenter() );
695 break;
696
697 case SHAPE_T::BEZIER:
698 shape->SetStart( primitive->GetStart() );
699 shape->SetEnd( primitive->GetEnd() );
700 shape->SetBezierC1( primitive->GetBezierC1() );
701 shape->SetBezierC2( primitive->GetBezierC2() );
702 break;
703
704 case SHAPE_T::POLY:
705 shape->SetPolyShape( primitive->GetPolyShape() );
706 break;
707
708 default:
710 }
711
712 shape->SetLocalCoord();
713 shape->Move( aPad->GetPosition() );
714 shape->Rotate( aPad->GetPosition(), aPad->GetOrientation() );
715 shape->SetLayer( layer );
716
717 commit.Add( shape );
718 }
719
720 aPad->SetShape( aPad->GetAnchorPadShape() );
721 aPad->DeletePrimitivesList();
722 aPad->SetFlags( ENTERED );
723 m_editPad = aPad->m_Uuid;
724 }
725
726 commit.Push( _("Edit pad shapes") );
728 return layer;
729}
730
731
732std::vector<FP_SHAPE*> PAD_TOOL::RecombinePad( PAD* aPad, bool aIsDryRun, BOARD_COMMIT& aCommit )
733{
734 int maxError = board()->GetDesignSettings().m_MaxError;
735 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aPad->GetParentFootprint() );
736
737 // Don't leave an object in the point editor that might no longer exist after
738 // recombining the pad.
740
741 for( BOARD_ITEM* item : footprint->GraphicalItems() )
742 item->ClearFlags( SKIP_STRUCT );
743
744 auto findNext =
745 [&]( PCB_LAYER_ID aLayer ) -> FP_SHAPE*
746 {
747 SHAPE_POLY_SET padPoly;
748 aPad->TransformShapeToPolygon( padPoly, aLayer, 0, maxError, ERROR_INSIDE );
749
750 for( BOARD_ITEM* item : footprint->GraphicalItems() )
751 {
752 FP_SHAPE* shape = dynamic_cast<FP_SHAPE*>( item );
753
754 if( !shape || ( shape->GetFlags() & SKIP_STRUCT ) )
755 continue;
756
757 if( shape->GetLayer() != aLayer )
758 continue;
759
760 if( shape->IsAnnotationProxy() ) // Pad number (and net name) box
761 return (FP_SHAPE*) item;
762
763 SHAPE_POLY_SET drawPoly;
764 shape->TransformShapeToPolygon( drawPoly, aLayer, 0, maxError, ERROR_INSIDE );
765 drawPoly.BooleanIntersection( padPoly, SHAPE_POLY_SET::PM_FAST );
766
767 if( !drawPoly.IsEmpty() )
768 return (FP_SHAPE*) item;
769 }
770
771 return nullptr;
772 };
773
774 auto findMatching =
775 [&]( FP_SHAPE* aShape ) -> std::vector<FP_SHAPE*>
776 {
777 std::vector<FP_SHAPE*> matching;
778
779 for( BOARD_ITEM* item : footprint->GraphicalItems() )
780 {
781 FP_SHAPE* other = dynamic_cast<FP_SHAPE*>( item );
782
783 if( !other || ( other->GetFlags() & SKIP_STRUCT ) )
784 continue;
785
786 if( aPad->GetLayerSet().test( other->GetLayer() )
787 && aShape->Compare( other ) == 0 )
788 {
789 matching.push_back( other );
790 }
791 }
792
793 return matching;
794 };
795
796 PCB_LAYER_ID layer;
797 std::vector<FP_SHAPE*> mergedShapes;
798
799 if( aPad->IsOnLayer( F_Cu ) )
800 layer = F_Cu;
801 else if( aPad->IsOnLayer( B_Cu ) )
802 layer = B_Cu;
803 else
804 layer = *aPad->GetLayerSet().UIOrder();
805
806 while( FP_SHAPE* fpShape = findNext( layer ) )
807 {
808 // We've found an intersecting item to combine.
809 //
810 fpShape->SetFlags( SKIP_STRUCT );
811
812 // First convert the pad to a custom-shape pad (if it isn't already)
813 //
814 if( !aIsDryRun )
815 {
816 aCommit.Modify( aPad );
817
818 if( aPad->GetShape() == PAD_SHAPE::RECT || aPad->GetShape() == PAD_SHAPE::CIRCLE )
819 {
820 aPad->SetAnchorPadShape( aPad->GetShape() );
821 }
822 else if( aPad->GetShape() != PAD_SHAPE::CUSTOM )
823 {
824 // Create a new minimally-sized circular anchor and convert existing pad
825 // to a polygon primitive
826 SHAPE_POLY_SET existingOutline;
827 aPad->TransformShapeToPolygon( existingOutline, layer, 0, maxError, ERROR_INSIDE );
828
830
831 if( aPad->GetSizeX() > aPad->GetSizeY() )
832 aPad->SetSizeX( aPad->GetSizeY() );
833
834 aPad->SetOffset( VECTOR2I( 0, 0 ) );
835
836 PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
837 shape->SetFilled( true );
839 shape->SetPolyShape( existingOutline );
840 shape->Move( - aPad->GetPosition() );
841 shape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
842
843 aPad->AddPrimitive( shape );
844 }
845
847 }
848
849 // Now add the new shape to the primitives list
850 //
851 mergedShapes.push_back( fpShape );
852
853 if( !aIsDryRun )
854 {
855 PCB_SHAPE* pcbShape = new PCB_SHAPE;
856
857 pcbShape->SetShape( fpShape->GetShape() );
858 pcbShape->SetFilled( fpShape->IsFilled() );
859 pcbShape->SetStroke( fpShape->GetStroke() );
860
861 switch( pcbShape->GetShape() )
862 {
863 case SHAPE_T::SEGMENT:
864 case SHAPE_T::RECT:
865 case SHAPE_T::CIRCLE:
866 pcbShape->SetStart( fpShape->GetStart() );
867 pcbShape->SetEnd( fpShape->GetEnd() );
868 break;
869
870 case SHAPE_T::ARC:
871 pcbShape->SetStart( fpShape->GetStart() );
872 pcbShape->SetEnd( fpShape->GetEnd() );
873 pcbShape->SetCenter( fpShape->GetCenter() );
874 break;
875
876 case SHAPE_T::BEZIER:
877 pcbShape->SetStart( fpShape->GetStart() );
878 pcbShape->SetEnd( fpShape->GetEnd() );
879 pcbShape->SetBezierC1( fpShape->GetBezierC1() );
880 pcbShape->SetBezierC2( fpShape->GetBezierC2() );
881 break;
882
883 case SHAPE_T::POLY:
884 pcbShape->SetPolyShape( fpShape->GetPolyShape() );
885 break;
886
887 default:
888 UNIMPLEMENTED_FOR( pcbShape->SHAPE_T_asString() );
889 }
890
891 pcbShape->Move( - aPad->GetPosition() );
892 pcbShape->Rotate( VECTOR2I( 0, 0 ), - aPad->GetOrientation() );
893 pcbShape->SetIsAnnotationProxy( fpShape->IsAnnotationProxy());
894 aPad->AddPrimitive( pcbShape );
895
896 aCommit.Remove( fpShape );
897 }
898
899 // See if there are other shapes that match and mark them for delete. (KiCad won't
900 // produce these, but old footprints from other vendors have them.)
901 for( FP_SHAPE* other : findMatching( fpShape ) )
902 {
903 other->SetFlags( SKIP_STRUCT );
904 mergedShapes.push_back( other );
905
906 if( !aIsDryRun )
907 aCommit.Remove( other );
908 }
909 }
910
911 for( BOARD_ITEM* item : footprint->GraphicalItems() )
912 item->ClearFlags( SKIP_STRUCT );
913
914 if( !aIsDryRun )
915 aPad->ClearFlags( ENTERED );
916
917 return mergedShapes;
918}
919
920
922{
926
929
932}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
@ NORMAL
Inactive layers are shown normally (no high-contrast mode)
static TOOL_ACTION cancelInteractive
Definition: actions.h:63
static TOOL_ACTION highContrastMode
Definition: actions.h:106
virtual void Revert() override
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Revert the commit by restoring the modified items state.
std::unique_ptr< PAD > m_Pad_Master
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:226
BOARD_ITEM_CONTAINER * GetParentFootprint() const
Definition: board_item.cpp:239
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:403
FOOTPRINTS & Footprints()
Definition: board.h:311
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
void Empty()
Clear the list.
Definition: collector.h:89
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
COMMIT & Remove(EDA_ITEM *aItem)
Notify observers that aItem has been removed.
Definition: commit.h:90
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Add a menu entry to run a TOOL_ACTION on selected items.
void AddSeparator(int aOrder=ANY_ORDER)
Add a separator to the menu.
static DELETED_BOARD_ITEM * GetInstance()
Definition: board_item.h:380
int GetStartNumber() const
Return common prefix for all enumerated pads.
wxString GetPrefix() const
WX_INFOBAR * GetInfoBar()
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void ForceRefresh()
Force a redraw.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
void SetStatusPopup(wxWindow *aPopup)
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:139
const KIID m_Uuid
Definition: eda_item.h:492
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:141
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:142
void SetBezierC2(const VECTOR2I &aPt)
Definition: eda_shape.h:178
void SetCenter(const VECTOR2I &aCenter)
Definition: eda_shape.cpp:470
void SetFilled(bool aFlag)
Definition: eda_shape.h:95
SHAPE_T GetShape() const
Definition: eda_shape.h:113
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: eda_shape.h:255
void SetStart(const VECTOR2I &aStart)
Definition: eda_shape.h:124
void SetShape(SHAPE_T aShape)
Definition: eda_shape.h:112
void SetEnd(const VECTOR2I &aEnd)
Definition: eda_shape.h:149
void SetBezierC1(const VECTOR2I &aPt)
Definition: eda_shape.h:175
wxString SHAPE_T_asString() const
Definition: eda_shape.cpp:75
bool IsAnnotationProxy() const
Definition: eda_shape.h:87
void SetIsAnnotationProxy(bool aIsProxy=true)
Definition: eda_shape.h:88
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:214
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
PADS & Pads()
Definition: footprint.h:170
const LIB_ID & GetFPID() const
Definition: footprint.h:212
DRAWINGS & GraphicalItems()
Definition: footprint.h:173
virtual void SetLocalCoord()
Set relative coordinates from draw coordinates.
Definition: fp_shape.cpp:52
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: fp_shape.cpp:343
void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: fp_shape.cpp:355
A general implementation of a COLLECTORS_GUIDE.
Definition: collectors.h:326
void SetIgnoreMTextsMarkedNoShow(bool ignore)
Definition: collectors.h:411
void SetIgnoreModulesRefs(bool ignore)
Definition: collectors.h:465
void SetIgnoreModulesVals(bool ignore)
Definition: collectors.h:459
void SetIgnoreMTextsOnFront(bool ignore)
Definition: collectors.h:423
void SetIgnoreMTextsOnBack(bool ignore)
Definition: collectors.h:417
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:204
void Collect(BOARD_ITEM *aItem, const std::vector< KICAD_T > &aScanList, const VECTOR2I &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class's Inspector method, which does the collection.
Definition: collectors.cpp:596
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition: pcb_painter.h:72
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Place the cursor immediately at a given point.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:77
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1591
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
void UpdateAllItemsConditionally(int aUpdateFlags, std::function< bool(VIEW_ITEM *)> aCondition)
Update items in the view according to the given flags and condition.
Definition: view.cpp:1494
LSEQ UIOrder() const
Definition: lset.cpp:922
Tool relating to pads and pad settings.
Definition: pad_tool.h:37
void Reset(RESET_REASON aReason) override
Basic initialization.
Definition: pad_tool.cpp:62
~PAD_TOOL()
React to model/view changes.
Definition: pad_tool.cpp:58
bool m_wasHighContrast
Definition: pad_tool.h:95
void setTransitions() override
< Bind handlers to corresponding TOOL_ACTIONs.
Definition: pad_tool.cpp:921
int EditPad(const TOOL_EVENT &aEvent)
Enter/exit WYSIWYG pad shape editing.
Definition: pad_tool.cpp:572
KIID m_editPad
Definition: pad_tool.h:96
int copyPadSettings(const TOOL_EVENT &aEvent)
Push pad settings from a pad to other pads on board or footprint.
Definition: pad_tool.cpp:168
int pastePadProperties(const TOOL_EVENT &aEvent)
Copy pad settings from a pad to the board design settings.
Definition: pad_tool.cpp:141
int PlacePad(const TOOL_EVENT &aEvent)
Place a pad in footprint editor.
Definition: pad_tool.cpp:492
std::vector< FP_SHAPE * > RecombinePad(PAD *aPad, bool aIsDryRun, BOARD_COMMIT &aCommit)
Recombine an exploded pad (or one produced with overlapping polygons in an older version).
Definition: pad_tool.cpp:732
int EnumeratePads(const TOOL_EVENT &aEvent)
Tool for quick pad enumeration.
Definition: pad_tool.cpp:283
PAD_TOOL()
Definition: pad_tool.cpp:51
PCB_LAYER_ID explodePad(PAD *aPad)
Definition: pad_tool.cpp:657
bool Init() override
Init() is called once upon a registration of the tool.
Definition: pad_tool.cpp:82
void SetLastPadNumber(const wxString &aPadNumber)
Definition: pad_tool.h:66
wxString m_lastPadNumber
Definition: pad_tool.h:93
int pushPadSettings(const TOOL_EVENT &aEvent)
Definition: pad_tool.cpp:240
Definition: pad.h:60
bool IsAperturePad() const
Definition: pad.h:408
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:398
int GetSizeX() const
Definition: pad.h:260
PAD_ATTRIB GetAttribute() const
Definition: pad.h:401
static LSET PTHMask()
layer set for a through hole pad
Definition: pad.cpp:196
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
Definition: pad.cpp:1586
void DeletePrimitivesList()
Clear the basic shapes list.
bool IsOnLayer(PCB_LAYER_ID aLayer, bool aIncludeCourtyards=false) const override
Test to see if this object is on the given layer.
Definition: pad.h:631
VECTOR2I GetPosition() const override
Definition: pad.h:203
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
Definition: pad.h:331
void SetOffset(const VECTOR2I &aOffset)
Definition: pad.h:274
void ImportSettingsFrom(const PAD &aMasterPad)
Import the pad settings from aMasterPad.
Definition: pad.cpp:1477
FOOTPRINT * GetParent() const
Definition: pad.cpp:1471
PAD_SHAPE GetShape() const
Definition: pad.h:195
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition: pad.h:371
static LSET SMDMask()
layer set for a SMD pad on Front layer
Definition: pad.cpp:203
void SetShape(PAD_SHAPE aShape)
Set the new shape of this pad.
Definition: pad.h:186
int GetSizeY() const
Definition: pad.h:262
void SetAnchorPadShape(PAD_SHAPE aShape)
Set the shape of the anchor pad for custom shaped pads.
Definition: pad.h:234
void AddPrimitive(PCB_SHAPE *aPrimitive)
Add item to the custom shape primitives list.
void SetSizeX(const int aX)
Definition: pad.h:259
PAD_SHAPE GetAnchorPadShape() const
Definition: pad.h:208
static TOOL_ACTION recombinePad
Definition: pcb_actions.h:429
static TOOL_ACTION enumeratePads
Tool for quick pad enumeration.
Definition: pcb_actions.h:432
static TOOL_ACTION pushPadSettings
Copy the current pad's settings to other pads in the footprint or on the board.
Definition: pcb_actions.h:452
static TOOL_ACTION mirrorH
Mirroring of selected items.
Definition: pcb_actions.h:129
static TOOL_ACTION copyPadSettings
Copy the selected pad's settings to the board design settings.
Definition: pcb_actions.h:446
static TOOL_ACTION placePad
Activation of the drawing tool (placing a PAD)
Definition: pcb_actions.h:426
static TOOL_ACTION properties
Activation of the edit tool.
Definition: pcb_actions.h:149
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
static TOOL_ACTION explodePad
Definition: pcb_actions.h:428
static TOOL_ACTION applyPadSettings
Copy the default pad settings to the selected pad.
Definition: pcb_actions.h:449
static TOOL_ACTION mirrorV
Definition: pcb_actions.h:130
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:126
static TOOL_ACTION rotateCw
Rotation of selected objects.
Definition: pcb_actions.h:122
static TOOL_ACTION rotateCcw
Definition: pcb_actions.h:123
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
EDA_ITEM * GetItem(const KIID &aId) const override
Fetch an item by KIID.
virtual BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Returns the BOARD_DESIGN_SETTINGS for the open project.
GENERAL_COLLECTORS_GUIDE GetCollectorsGuide()
virtual void SetActiveLayer(PCB_LAYER_ID aLayer)
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
virtual void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
Definition: pcb_shape.cpp:191
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
Definition: pcb_shape.cpp:390
virtual void Move(const VECTOR2I &aMoveVector) override
Move this object.
Definition: pcb_shape.cpp:163
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: pcb_shape.h:72
KIGFX::PCB_VIEW * view() const
PCB_BASE_EDIT_FRAME * frame() const
BOARD * board() const
PCB_DRAW_PANEL_GAL * canvas() const
@ IPO_FLIP
Handle flip action in the loop by calling the item's flip method.
@ IPO_ROTATE
Handle the rotate action in the loop by calling the item's rotate method.
@ IPO_SINGLE_CLICK
Create an item immediately on placement starting, otherwise show the pencil cursor until the item is ...
@ IPO_REPEAT
Allow repeat placement of the item.
bool m_isFootprintEditor
void doInteractiveItemPlacement(const TOOL_EVENT &aTool, INTERACTIVE_PLACER_BASE *aPlacer, const wxString &aCommitMessage, int aOptions=IPO_ROTATE|IPO_FLIP|IPO_REPEAT)
Helper function for performing a common interactive idiom: wait for a left click, place an item there...
const PCB_SELECTION & selection() const
FOOTPRINT * footprint() const
static SELECTION_CONDITION HasType(KICAD_T aType)
Create a functor that tests if among the selected items there is at least one of a given type.
static SELECTION_CONDITION Count(int aNumber)
Create a functor that tests if the number of selected items is equal to the value given as parameter.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
static SELECTION_CONDITION OnlyTypes(std::vector< KICAD_T > aTypes)
Create a functor that tests if the selected items are only of given types.
int Size() const
Returns the number of selected parts.
Definition: selection.h:115
Represent a set of closed polygons.
bool IsEmpty() const
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union between a and b, store the result in it self For aFastMode meaning,...
wxWindow * GetPanel()
Definition: status_popup.h:62
virtual void Popup(wxWindow *aFocus=nullptr)
virtual void Move(const wxPoint &aWhere)
Extension of STATUS_POPUP for displaying a single line text.
Definition: status_popup.h:83
void SetText(const wxString &aText)
Display a text.
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
int GetHotKey() const
Return the hotkey keycode which initiates the action.
Definition: tool_action.h:111
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ MODEL_RELOAD
Model changes (required full reload)
Definition: tool_base.h:80
Generic, UI-independent tool event.
Definition: tool_event.h:156
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).
TOOL_MENU & GetToolMenu()
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
A modified version of the wxInfoBar class that allows us to:
Definition: wx_infobar.h:75
void RemoveAllButtons()
Remove all the buttons that have been added by the user.
Definition: wx_infobar.cpp:289
void Dismiss() override
Dismisses the infobar and updates the containing layout and AUI manager (if one is provided).
Definition: wx_infobar.cpp:175
void ShowMessage(const wxString &aMessage, int aFlags=wxICON_INFORMATION) override
Show the info bar with the provided message and icon.
Definition: wx_infobar.cpp:142
static PCB_SHAPE * findNext(PCB_SHAPE *aShape, const VECTOR2I &aPoint, const std::vector< PCB_SHAPE * > &aList, unsigned aLimit)
Searches for a PCB_SHAPE matching a given end point or start point in a list.
static bool empty(const wxTextEntryBase *aCtrl)
#define _(s)
#define ENTERED
indicates a group has been entered
#define SKIP_STRUCT
flag indicating that the structure should be ignored
@ FP_SMD
Definition: footprint.h:69
@ FP_THROUGH_HOLE
Definition: footprint.h:68
@ ERROR_INSIDE
wxString KeyNameFromKeyCode(int aKeycode, bool *aIsFound)
Return the key name from the key code.
KIID niluuid(0)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ B_Cu
Definition: layer_ids.h:95
@ F_Cu
Definition: layer_ids.h:64
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition: macros.h:120
@ REPAINT
Item needs to be redrawn.
Definition: view_item.h:52
@ ALL
All except INITIAL_ADD.
Definition: view_item.h:53
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
@ CONN
Like smd, does not appear on the solder paste layer (default)
static void doPushPadProperties(BOARD &board, const PAD &aSrcPad, BOARD_COMMIT &commit, bool aSameFootprints, bool aPadShapeFilter, bool aPadOrientFilter, bool aPadLayerFilter, bool aPadTypeFilter)
Definition: pad_tool.cpp:189
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
std::function< bool(const SELECTION &)> SELECTION_CONDITION
< Functor type that checks a specific condition for selected items.
const double IU_PER_MM
Definition: base_units.h:77
MAGNETIC_OPTIONS tracks
MAGNETIC_OPTIONS pads
@ BUT_LEFT
Definition: tool_event.h:127
@ BUT_RIGHT
Definition: tool_event.h:128
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590