KiCad PCB EDA Suite
convert_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) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
5  * @author Jon Evans <jon@craftyjon.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <bitmaps.h>
26 #include <board_commit.h>
27 #include <board.h>
28 #include <pcb_shape.h>
29 #include <fp_shape.h>
30 #include <track.h>
31 #include <zone.h>
32 #include <collectors.h>
33 #include <confirm.h>
34 #include <menus_helpers.h>
35 #include <pcb_edit_frame.h>
36 #include <footprint_edit_frame.h>
37 #include <trigo.h>
38 #include <tool/tool_manager.h>
39 #include <tools/edit_tool.h>
40 #include <tools/pcb_actions.h>
43 
44 #include "convert_tool.h"
45 
46 
48  TOOL_INTERACTIVE( "pcbnew.Convert" ),
49  m_selectionTool( NULL ),
50  m_menu( NULL ),
51  m_frame( NULL )
52 {
53 }
54 
56 {
57  delete m_menu;
58 }
59 
60 
63 
64 
66 {
68  m_frame = getEditFrame<PCB_BASE_FRAME>();
69 
70  // Create a context menu and make it available through selection tool
71  m_menu = new CONDITIONAL_MENU( this );
73  m_menu->SetTitle( _( "Convert" ) );
74 
75  static KICAD_T convertableTracks[] = { PCB_TRACE_T, PCB_ARC_T, EOT };
76  static KICAD_T zones[] = { PCB_ZONE_T, PCB_FP_ZONE_T, EOT };
77 
78  auto graphicLines = P_S_C::OnlyGraphicShapeTypes( { S_SEGMENT, S_RECT, S_CIRCLE } )
79  && P_S_C::SameLayer();
80 
81  auto trackLines = S_C::MoreThan( 1 ) && S_C::OnlyTypes( convertableTracks )
82  && P_S_C::SameLayer();
83 
84  auto anyLines = graphicLines || trackLines;
85 
86  auto anyPolys = S_C::OnlyTypes( zones )
88 
89  auto lineToArc = S_C::Count( 1 ) && ( P_S_C::OnlyGraphicShapeTypes( { S_SEGMENT } )
90  || S_C::OnlyType( PCB_TRACE_T ) );
91 
92  auto showConvert = anyPolys || anyLines || lineToArc;
93 
98 
99  // Currently the code exists, but tracks are not really existing in footprints
100  // only segments on copper layers
103 
105 
107  selToolMenu.AddMenu( m_menu, showConvert, 100 );
108 
109  return true;
110 }
111 
112 
114 {
115  FOOTPRINT* parentFootprint = nullptr;
116 
117  auto& selection = m_selectionTool->RequestSelection(
118  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
119  {
120  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
121  {
122  BOARD_ITEM* item = aCollector[i];
123 
124  switch( item->Type() )
125  {
126  case PCB_SHAPE_T:
127  case PCB_FP_SHAPE_T:
128  switch( static_cast<PCB_SHAPE*>( item )->GetShape() )
129  {
130  case S_SEGMENT:
131  case S_RECT:
132  case S_CIRCLE:
133  // case S_ARC: // Not yet
134  break;
135 
136  default:
137  aCollector.Remove( item );
138  }
139 
140  break;
141 
142  case PCB_TRACE_T:
143  // case PCB_ARC_T: // Not yet
144  break;
145 
146  default:
147  aCollector.Remove( item );
148  }
149  }
150  } );
151 
152  if( selection.Empty() )
153  return 0;
154 
155  // TODO(JE) From a context menu, the selection condition enforces that the items are on
156  // a single layer. But, you can still trigger this with items on multiple layer selected.
157  // Technically we should make this work if each contiguous poly shares a layer
158  PCB_LAYER_ID destLayer = static_cast<BOARD_ITEM*>( selection.Front() )->GetLayer();
159 
160  SHAPE_POLY_SET polySet = makePolysFromSegs( selection.GetItems() );
161 
162  polySet.Append( makePolysFromRects( selection.GetItems() ) );
163 
164  polySet.Append( makePolysFromCircles( selection.GetItems() ) );
165 
166  if( polySet.IsEmpty() )
167  return 0;
168 
169  bool isFootprint = m_frame->IsType( FRAME_FOOTPRINT_EDITOR );
170 
171  if( FP_SHAPE* graphic = dynamic_cast<FP_SHAPE*>( selection.Front() ) )
172  parentFootprint = graphic->GetParentFootprint();
173 
174  BOARD_COMMIT commit( m_frame );
175 
176  // For now, we convert each outline in the returned shape to its own polygon
177  std::vector<SHAPE_POLY_SET> polys;
178 
179  for( int i = 0; i < polySet.OutlineCount(); i++ )
180  polys.emplace_back( SHAPE_POLY_SET( polySet.COutline( i ) ) );
181 
182  if( aEvent.IsAction( &PCB_ACTIONS::convertToPoly ) )
183  {
184  for( const SHAPE_POLY_SET& poly : polys )
185  {
186  PCB_SHAPE* graphic = isFootprint ? new FP_SHAPE( parentFootprint ) : new PCB_SHAPE;
187 
188  graphic->SetShape( S_POLYGON );
189  graphic->SetFilled( destLayer != Edge_Cuts );
190  graphic->SetLayer( destLayer );
191  graphic->SetPolyShape( poly );
192 
193  commit.Add( graphic );
194  }
195 
196  commit.Push( _( "Convert shapes to polygon" ) );
197  }
198  else
199  {
200  // Creating zone or keepout
201  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
202  BOARD_ITEM_CONTAINER* parent = frame->GetModel();
203  ZONE_SETTINGS zoneInfo = frame->GetZoneSettings();
204 
205  int ret;
206 
207  if( aEvent.IsAction( &PCB_ACTIONS::convertToKeepout ) )
208  ret = InvokeRuleAreaEditor( frame, &zoneInfo );
209  else
210  ret = InvokeCopperZonesEditor( frame, &zoneInfo );
211 
212  if( ret == wxID_CANCEL )
213  return 0;
214 
215  for( const SHAPE_POLY_SET& poly : polys )
216  {
217  ZONE* zone = isFootprint ? new FP_ZONE( parent ) : new ZONE( parent );
218 
219  *zone->Outline() = poly;
220  zone->HatchBorder();
221 
222  zoneInfo.ExportSetting( *zone );
223 
224  commit.Add( zone );
225  }
226 
227  commit.Push( _( "Convert shapes to zone" ) );
228  }
229 
230  return 0;
231 }
232 
233 
234 SHAPE_POLY_SET CONVERT_TOOL::makePolysFromSegs( const std::deque<EDA_ITEM*>& aItems )
235 {
236  SHAPE_POLY_SET poly;
237 
238  std::map<VECTOR2I, std::vector<EDA_ITEM*>> connections;
239  std::set<EDA_ITEM*> used;
240  std::deque<EDA_ITEM*> toCheck;
241 
242  for( EDA_ITEM* item : aItems )
243  {
244  if( OPT<SEG> seg = getStartEndPoints( item ) )
245  {
246  toCheck.push_back( item );
247  connections[seg->A].emplace_back( item );
248  connections[seg->B].emplace_back( item );
249  }
250  }
251 
252  while( !toCheck.empty() )
253  {
254  EDA_ITEM* candidate = toCheck.front();
255  toCheck.pop_front();
256 
257  if( used.count( candidate ) )
258  continue;
259 
260  OPT<SEG> seg = getStartEndPoints( candidate );
261  wxASSERT( seg );
262 
263  SHAPE_LINE_CHAIN outline;
264  std::deque<VECTOR2I> points;
265 
266  // aDirection == true for walking "right" and appending to the end of points
267  // false for walking "left" and prepending to the beginning
268  std::function<void( EDA_ITEM*, bool )> process =
269  [&]( EDA_ITEM* aItem, bool aDirection )
270  {
271  if( used.count( aItem ) )
272  return;
273 
274  used.insert( aItem );
275 
276  OPT<SEG> nextSeg = getStartEndPoints( aItem );
277  wxASSERT( nextSeg );
278 
279  // The reference point, i.e. last added point in the direction we're headed
280  VECTOR2I& ref = aDirection ? points.back() : points.front();
281 
282  // The next point, i.e. the other point on this segment
283  VECTOR2I& next = ( ref == nextSeg->A ) ? nextSeg->B : nextSeg->A;
284 
285  if( aDirection )
286  points.push_back( next );
287  else
288  points.push_front( next );
289 
290  for( EDA_ITEM* neighbor : connections[next] )
291  process( neighbor, aDirection );
292  };
293 
294  // Start with just one point and walk one direction
295  points.push_back( seg->A );
296  process( candidate, true );
297 
298  // check for any candidates on the "left"
299  EDA_ITEM* left = nullptr;
300 
301  for( EDA_ITEM* possibleLeft : connections[seg->A] )
302  {
303  if( possibleLeft != candidate )
304  {
305  left = possibleLeft;
306  break;
307  }
308  }
309 
310  if( left )
311  process( left, false );
312 
313  if( points.size() < 3 )
314  continue;
315 
316  for( const VECTOR2I& point : points )
317  outline.Append( point );
318 
319  outline.SetClosed( true );
320 
321  poly.AddOutline( outline );
322  }
323 
324  return poly;
325 }
326 
327 
328 SHAPE_POLY_SET CONVERT_TOOL::makePolysFromRects( const std::deque<EDA_ITEM*>& aItems )
329 {
330  SHAPE_POLY_SET poly;
331 
332  for( EDA_ITEM* item : aItems )
333  {
334  if( item->Type() != PCB_SHAPE_T && item->Type() != PCB_FP_SHAPE_T )
335  continue;
336 
337  PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( item );
338 
339  if( graphic->GetShape() != S_RECT )
340  continue;
341 
342  SHAPE_LINE_CHAIN outline;
343  VECTOR2I start( graphic->GetStart() );
344  VECTOR2I end( graphic->GetEnd() );
345 
346  outline.Append( start );
347  outline.Append( VECTOR2I( end.x, start.y ) );
348  outline.Append( end );
349  outline.Append( VECTOR2I( start.x, end.y ) );
350  outline.SetClosed( true );
351 
352  poly.AddOutline( outline );
353  }
354 
355  return poly;
356 }
357 
358 
359 SHAPE_POLY_SET CONVERT_TOOL::makePolysFromCircles( const std::deque<EDA_ITEM*>& aItems )
360 {
361  SHAPE_POLY_SET poly;
362 
363  for( EDA_ITEM* item : aItems )
364  {
365  if( item->Type() != PCB_SHAPE_T && item->Type() != PCB_FP_SHAPE_T )
366  continue;
367 
368  PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( item );
369 
370  if( graphic->GetShape() != S_CIRCLE )
371  continue;
372 
373  BOARD_DESIGN_SETTINGS& bds = graphic->GetBoard()->GetDesignSettings();
374  SHAPE_LINE_CHAIN outline;
375 
376  TransformCircleToPolygon( outline, graphic->GetPosition(), graphic->GetRadius(),
377  bds.m_MaxError, ERROR_OUTSIDE );
378 
379  poly.AddOutline( outline );
380  }
381 
382  return poly;
383 }
384 
385 
387 {
388  auto& selection = m_selectionTool->RequestSelection(
389  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
390  {
391  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
392  {
393  BOARD_ITEM* item = aCollector[i];
394 
395  switch( item->Type() )
396  {
397  case PCB_SHAPE_T:
398  case PCB_FP_SHAPE_T:
399  switch( static_cast<PCB_SHAPE*>( item )->GetShape() )
400  {
401  case S_POLYGON:
402  break;
403 
404  case S_RECT:
405  break;
406 
407  default:
408  aCollector.Remove( item );
409  }
410 
411  break;
412 
413  case PCB_ZONE_T:
414  case PCB_FP_ZONE_T:
415  break;
416 
417  default:
418  aCollector.Remove( item );
419  }
420  }
421  } );
422 
423  if( selection.Empty() )
424  return 0;
425 
426  auto getPolySet =
427  []( EDA_ITEM* aItem )
428  {
429  SHAPE_POLY_SET set;
430 
431  switch( aItem->Type() )
432  {
433  case PCB_ZONE_T:
434  case PCB_FP_ZONE_T:
435  set = *static_cast<ZONE*>( aItem )->Outline();
436  break;
437 
438  case PCB_SHAPE_T:
439  case PCB_FP_SHAPE_T:
440  {
441  PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( aItem );
442 
443  if( graphic->GetShape() == S_POLYGON )
444  {
445  set = graphic->GetPolyShape();
446  }
447  else if( graphic->GetShape() == S_RECT )
448  {
449  SHAPE_LINE_CHAIN outline;
450  VECTOR2I start( graphic->GetStart() );
451  VECTOR2I end( graphic->GetEnd() );
452 
453  outline.Append( start );
454  outline.Append( VECTOR2I( end.x, start.y ) );
455  outline.Append( end );
456  outline.Append( VECTOR2I( start.x, end.y ) );
457  outline.SetClosed( true );
458 
459  set.AddOutline( outline );
460  }
461  else
462  {
463  wxFAIL_MSG( "Unhandled graphic shape type in PolyToLines - getPolySet" );
464  }
465  break;
466  }
467 
468  default:
469  wxFAIL_MSG( "Unhandled type in PolyToLines - getPolySet" );
470  break;
471  }
472 
473  return set;
474  };
475 
476  auto getSegList =
477  []( SHAPE_POLY_SET& aPoly )
478  {
479  std::vector<SEG> segs;
480 
481  // Our input should be valid polys, so OK to assert here
482  wxASSERT( aPoly.VertexCount() >= 2 );
483 
484  for( int i = 1; i < aPoly.VertexCount(); i++ )
485  segs.emplace_back( SEG( aPoly.CVertex( i - 1 ), aPoly.CVertex( i ) ) );
486 
487  segs.emplace_back( SEG( aPoly.CVertex( aPoly.VertexCount() - 1 ),
488  aPoly.CVertex( 0 ) ) );
489 
490  return segs;
491  };
492 
493  BOARD_COMMIT commit( m_frame );
494  FOOTPRINT_EDIT_FRAME* fpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
495 
496  FOOTPRINT* footprint = nullptr;
497 
498  if( fpEditor )
499  footprint = fpEditor->GetBoard()->GetFirstFootprint();
500 
501  for( EDA_ITEM* item : selection )
502  {
503  PCB_LAYER_ID layer = static_cast<BOARD_ITEM*>( item )->GetLayer();
504  SHAPE_POLY_SET polySet = getPolySet( item );
505  std::vector<SEG> segs = getSegList( polySet );
506 
507  if( aEvent.IsAction( &PCB_ACTIONS::convertToLines ) )
508  {
509  for( SEG& seg : segs )
510  {
511  if( fpEditor )
512  {
513  FP_SHAPE* graphic = new FP_SHAPE( footprint, S_SEGMENT );
514 
515  graphic->SetLayer( layer );
516  graphic->SetStart( wxPoint( seg.A ) );
517  graphic->SetStart0( wxPoint( seg.A ) );
518  graphic->SetEnd( wxPoint( seg.B ) );
519  graphic->SetEnd0( wxPoint( seg.B ) );
520  commit.Add( graphic );
521  }
522  else
523  {
524  PCB_SHAPE* graphic = new PCB_SHAPE;
525 
526  graphic->SetShape( S_SEGMENT );
527  graphic->SetLayer( layer );
528  graphic->SetStart( wxPoint( seg.A ) );
529  graphic->SetEnd( wxPoint( seg.B ) );
530  commit.Add( graphic );
531  }
532  }
533  }
534  else
535  {
536  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
537  BOARD_ITEM_CONTAINER* parent = frame->GetModel();
538 
539  if( !IsCopperLayer( layer ) )
540  layer = frame->SelectOneLayer( F_Cu, LSET::AllNonCuMask() );
541 
542  // I am really unsure converting a polygon to "tracks" (i.e. segments on
543  // copper layers) make sense for footprints, but anyway this code exists
544  if( fpEditor )
545  {
546  // Creating segments on copper layer
547  for( SEG& seg : segs )
548  {
549  FP_SHAPE* graphic = new FP_SHAPE( footprint, S_SEGMENT );
550  graphic->SetLayer( layer );
551  graphic->SetStart( wxPoint( seg.A ) );
552  graphic->SetStart0( wxPoint( seg.A ) );
553  graphic->SetEnd( wxPoint( seg.B ) );
554  graphic->SetEnd0( wxPoint( seg.B ) );
555  commit.Add( graphic );
556  }
557  }
558  else
559  {
560  // Creating tracks
561  for( SEG& seg : segs )
562  {
563  TRACK* track = new TRACK( parent );
564 
565  track->SetLayer( layer );
566  track->SetStart( wxPoint( seg.A ) );
567  track->SetEnd( wxPoint( seg.B ) );
568  commit.Add( track );
569  }
570  }
571  }
572  }
573 
574  commit.Push( _( "Convert polygons to lines" ) );
575 
576  return 0;
577 }
578 
579 
581 {
582  auto& selection = m_selectionTool->RequestSelection(
583  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
584  {
585  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
586  {
587  BOARD_ITEM* item = aCollector[i];
588 
589  if( !( item->Type() == PCB_SHAPE_T ||
590  item->Type() == PCB_TRACE_T ||
591  item->Type() == PCB_FP_SHAPE_T ) )
592  {
593  aCollector.Remove( item );
594  }
595  }
596  } );
597 
598  EDA_ITEM* source = selection.Front();
599  VECTOR2I start, end, mid;
600 
601  // Offset the midpoint along the normal a little bit so that it's more obviously an arc
602  const double offsetRatio = 0.1;
603 
604  if( OPT<SEG> seg = getStartEndPoints( source ) )
605  {
606  start = seg->A;
607  end = seg->B;
608 
609  VECTOR2I normal = ( seg->B - seg->A ).Perpendicular().Resize( offsetRatio * seg->Length() );
610  mid = seg->Center() + normal;
611  }
612  else
613  return -1;
614 
615  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
616  BOARD_ITEM_CONTAINER* parent = frame->GetModel();
617 
618  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( source );
619 
620  // Don't continue processing if we don't actually have a board item
621  if( !boardItem )
622  return 0;
623 
624  PCB_LAYER_ID layer = boardItem->GetLayer();
625 
626  BOARD_COMMIT commit( m_frame );
627 
628  if( source->Type() == PCB_SHAPE_T || source->Type() == PCB_FP_SHAPE_T )
629  {
630  PCB_SHAPE* line = static_cast<PCB_SHAPE*>( source );
631  PCB_SHAPE* arc = new PCB_SHAPE( parent );
632 
633  VECTOR2I center = GetArcCenter( start, mid, end );
634 
635  arc->SetShape( S_ARC );
636  arc->SetFilled( false );
637  arc->SetLayer( layer );
638  arc->SetWidth( line->GetWidth() );
639 
640  arc->SetCenter( wxPoint( center ) );
641  arc->SetArcStart( wxPoint( start ) );
642  arc->SetAngle( GetArcAngle( start, mid, end ) );
643 
644  arc->SetArcEnd( wxPoint( end ) );
645  commit.Add( arc );
646  }
647  else
648  {
649  wxASSERT( source->Type() == PCB_TRACE_T );
650  TRACK* line = static_cast<TRACK*>( source );
651  ARC* arc = new ARC( parent );
652 
653  arc->SetLayer( layer );
654  arc->SetWidth( line->GetWidth() );
655  arc->SetStart( wxPoint( start ) );
656  arc->SetMid( wxPoint( mid ) );
657  arc->SetEnd( wxPoint( end ) );
658 
659  commit.Add( arc );
660  }
661 
662  commit.Push( _( "Create arc from line segment" ) );
663 
664  return 0;
665 }
666 
667 
669 {
670  switch( aItem->Type() )
671  {
672  case PCB_SHAPE_T:
673  case PCB_FP_SHAPE_T:
674  {
675  PCB_SHAPE* line = static_cast<PCB_SHAPE*>( aItem );
676  return boost::make_optional<SEG>( { VECTOR2I( line->GetStart() ),
677  VECTOR2I( line->GetEnd() ) } );
678  }
679 
680  case PCB_TRACE_T:
681  {
682  TRACK* line = static_cast<TRACK*>( aItem );
683  return boost::make_optional<SEG>( { VECTOR2I( line->GetStart() ),
684  VECTOR2I( line->GetEnd() ) } );
685  }
686 
687  case PCB_ARC_T:
688  {
689  ARC* arc = static_cast<ARC*>( aItem );
690  return boost::make_optional<SEG>( { VECTOR2I( arc->GetStart() ),
691  VECTOR2I( arc->GetEnd() ) } );
692  }
693 
694  default:
695  return NULLOPT;
696  }
697 }
698 
699 
701 {
708 }
PCB_LAYER_ID SelectOneLayer(PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask=LSET(), wxPoint aDlgPosition=wxDefaultPosition)
Show the dialog box for a layer selection.
Definition: sel_layer.cpp:225
CITER next(CITER it)
Definition: ptree.cpp:126
void AddMenu(ACTION_MENU *aMenu, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Add a submenu to the menu.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
void SetEnd0(const wxPoint &aPoint)
Definition: fp_shape.h:114
double GetArcAngle(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Returns the subtended angle for a given arc.
Definition: trigo.cpp:492
static TOOL_ACTION convertToTracks
Definition: pcb_actions.h:474
static OPT< SEG > getStartEndPoints(EDA_ITEM *aItem)
Retrieve the start and end points for a generic item.
SHAPE_POLY_SET & GetPolyShape()
Definition: pcb_shape.h:268
static TOOL_ACTION convertToLines
Definition: pcb_actions.h:472
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Definition: pcb_shape.h:156
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:194
This file is part of the common library.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
void SetEnd(const wxPoint &aEnd)
Definition: track.h:112
static SELECTION_CONDITION MoreThan(int aNumber)
Create a functor that tests if the number of selected items is greater than the value given as parame...
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
const wxPoint & GetStart() const
Definition: track.h:116
const BITMAP_OPAQUE convert_xpm[1]
Definition: convert.cpp:61
static SELECTION_CONDITION OnlyTypes(const KICAD_T aTypes[])
Create a functor that tests if the selected items are only of given types.
void SetFilled(bool aFlag)
Definition: pcb_shape.h:94
SHAPE_POLY_SET * Outline()
Definition: zone.h:323
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
Definition: pcb_shape.h:201
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
bool IsEmpty() const
int GetWidth() const
Definition: pcb_shape.h:118
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:773
static SELECTION_CONDITION OnlyGraphicShapeTypes(const std::set< PCB_SHAPE_TYPE_T > aTypes)
Create a functor that tests if the selection contains PCB_SHAPE* items of certain shapes.
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:54
static SHAPE_POLY_SET makePolysFromCircles(const std::deque< EDA_ITEM * > &aItems)
Try to make polygons from circles.
TOOL_MENU & GetToolMenu()
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
Class that groups generic conditions for selected items.
usual segment : line with rounded ends
Definition: board_item.h:50
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:591
Arcs (with rounded ends)
Definition: board_item.h:52
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
segment with non rounded ends
Definition: board_item.h:51
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.
PCB_SELECTION_TOOL * m_selectionTool
Definition: convert_tool.h:103
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
static SELECTION_CONDITION SameLayer()
Creates a functor that tests if selection contains items that belong exclusively to the same layer.
static SHAPE_POLY_SET makePolysFromRects(const std::deque< EDA_ITEM * > &aItems)
Try to make polygons from rectangles.
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).
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:115
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void SetWidth(int aWidth)
Definition: track.h:109
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:70
virtual ~CONVERT_TOOL()
int LinesToPoly(const TOOL_EVENT &aEvent)
Convert selected lines to a polygon, if possible.
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
void SetClosed(bool aClosed)
Function SetClosed()
PCB_LAYER_ID
A quick note on layer IDs:
FOOTPRINT * GetFirstFootprint() const
Gets the first footprint on the board or nullptr.
Definition: board.h:380
const auto NULLOPT
Definition: optional.h:9
#define NULL
void SetShape(PCB_SHAPE_TYPE_T aShape)
Definition: pcb_shape.h:129
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
void HatchBorder()
Function HatchBorder computes the hatch lines depending on the hatch parameters and stores it in the ...
Definition: zone.cpp:923
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
void SetIcon(const BITMAP_OPAQUE *aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:71
const ZONE_SETTINGS & GetZoneSettings() const
Generic, UI-independent tool event.
Definition: tool_event.h:173
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Definition: pcb_shape.h:145
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
static TOOL_ACTION convertToZone
Definition: pcb_actions.h:470
static TOOL_ACTION convertToKeepout
Definition: pcb_actions.h:471
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:105
void SetCenter(const wxPoint &aCenterPoint)
For arcs and circles:
Definition: pcb_shape.h:229
void SetMid(const wxPoint &aMid)
Definition: track.h:291
void SetStart0(const wxPoint &aPoint)
Definition: fp_shape.h:111
int InvokeRuleAreaEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeRuleAreaEditor invokes up a modal dialog window for copper zone editing.
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:67
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
Definition: seg.h:41
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
wxPoint GetPosition() const override
Definition: pcb_shape.cpp:67
PCB_BASE_FRAME * m_frame
Definition: convert_tool.h:105
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:404
static TOOL_ACTION convertToArc
Definition: pcb_actions.h:473
CONDITIONAL_MENU * m_menu
Definition: convert_tool.h:104
bool Init() override
Init() is called once upon a registration of the tool.
void SetTitle(const wxString &aTitle) override
Set title for the menu.
Definition: action_menu.cpp:89
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, bool aConfirmLockedItems=false)
Return the current selection set, filtered according to aFlags and aClientFilter.
bool IsType(FRAME_T aType) const
Common, abstract interface for edit frames.
Definition: track.h:262
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:148
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:241
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
static SELECTION_CONDITION OnlyType(KICAD_T aType)
Create a functor that tests if the selected items are only of given type.
class ZONE, managed by a footprint
Definition: typeinfo.h:94
void process(const BOARD_CONNECTED_ITEM *item, int net)
void SetWidth(int aWidth)
Definition: pcb_shape.h:117
The selection tool: currently supports:
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aCornerBuffer, wxPoint aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Revert the commit by restoring the modified items state.
const wxPoint & GetEnd() const
Definition: track.h:113
void SetArcEnd(const wxPoint &aArcEndPoint)
Initialize the end arc point.
Definition: pcb_shape.h:222
boost::optional< T > OPT
Definition: optional.h:7
static bool GetLayer(MODEL_VRML &aModel, LAYER_NUM layer, VRML_LAYER **vlayer)
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
int InvokeCopperZonesEditor(PCB_BASE_FRAME *aCaller, ZONE_SETTINGS *aSettings)
Function InvokeCopperZonesEditor invokes up a modal dialog window for copper zone editing.
ring
Definition: board_item.h:53
void SetStart(const wxPoint &aStart)
Definition: track.h:115
static TOOL_ACTION convertToPoly
Definition: pcb_actions.h:469
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: pcb_shape.h:276
int PolyToLines(const TOOL_EVENT &aEvent)
Convert selected polygon-like object to graphic lines, if possible.
static SHAPE_POLY_SET makePolysFromSegs(const std::deque< EDA_ITEM * > &aItems)
Try to make polygons from segments in the selected items.
PCB_SHAPE_TYPE_T GetShape() const
Definition: pcb_shape.h:130
Abstract interface for BOARD_ITEMs capable of storing other items inside.
BOARD * GetBoard() const
const VECTOR2I GetArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:450
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Sets the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:465
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
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.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
FP_ZONE is a specialization of ZONE for use in footprints.
Definition: zone.h:965
Definition: track.h:83
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:159
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:213
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
int SegmentToArc(const TOOL_EVENT &aEvent)
Convert selected segment (graphic or track) to an arc of the same type.
Container for design settings for a BOARD object.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...