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 <board_design_settings.h>
29 #include <pcb_shape.h>
30 #include <fp_shape.h>
31 #include <pcb_track.h>
32 #include <zone.h>
33 #include <collectors.h>
34 #include <confirm.h>
35 #include <menus_helpers.h>
36 #include <pcb_edit_frame.h>
37 #include <footprint_edit_frame.h>
38 #include <trigo.h>
39 #include <tool/tool_manager.h>
40 #include <tools/edit_tool.h>
41 #include <tools/pcb_actions.h>
44 
45 #include "convert_tool.h"
46 
47 
49  TOOL_INTERACTIVE( "pcbnew.Convert" ),
50  m_selectionTool( NULL ),
51  m_menu( NULL ),
52  m_frame( NULL )
53 {
54 }
55 
57 {
58  delete m_menu;
59 }
60 
61 
64 
65 
67 {
69  m_frame = getEditFrame<PCB_BASE_FRAME>();
70 
71  // Create a context menu and make it available through selection tool
72  m_menu = new CONDITIONAL_MENU( this );
74  m_menu->SetTitle( _( "Convert" ) );
75 
76  static KICAD_T convertableTracks[] = { PCB_TRACE_T, PCB_ARC_T, EOT };
77  static KICAD_T zones[] = { PCB_ZONE_T, PCB_FP_ZONE_T, EOT };
78 
81  && P_S_C::SameLayer();
82 
83  auto trackLines = S_C::MoreThan( 1 ) && S_C::OnlyTypes( convertableTracks )
84  && P_S_C::SameLayer();
85 
86  auto anyLines = graphicLines || trackLines;
87 
88  auto anyPolys = S_C::OnlyTypes( zones )
91 
92  auto lineToArc = S_C::Count( 1 )
94  || S_C::OnlyType( PCB_TRACE_T ) );
95 
96  auto showConvert = anyPolys || anyLines || lineToArc;
97 
102 
103  // Currently the code exists, but tracks are not really existing in footprints
104  // only segments on copper layers
107 
109 
111  selToolMenu.AddMenu( m_menu, showConvert, 100 );
112 
113  return true;
114 }
115 
116 
118 {
119  FOOTPRINT* parentFootprint = nullptr;
120 
121  auto& selection = m_selectionTool->RequestSelection(
122  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
123  {
124  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
125  {
126  BOARD_ITEM* item = aCollector[i];
127 
128  switch( item->Type() )
129  {
130  case PCB_SHAPE_T:
131  case PCB_FP_SHAPE_T:
132  switch( static_cast<PCB_SHAPE*>( item )->GetShape() )
133  {
137  // case S_ARC: // Not yet
138  break;
139 
140  default:
141  aCollector.Remove( item );
142  }
143 
144  break;
145 
146  case PCB_TRACE_T:
147  // case PCB_ARC_T: // Not yet
148  break;
149 
150  default:
151  aCollector.Remove( item );
152  }
153  }
154  } );
155 
156  if( selection.Empty() )
157  return 0;
158 
159  PCB_LAYER_ID destLayer = m_frame->GetActiveLayer();
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( PCB_SHAPE_TYPE::POLYGON );
189  graphic->SetFilled( false );
190  graphic->SetWidth( poly.Outline( 0 ).Width() );
191  graphic->SetLayer( destLayer );
192  graphic->SetPolyShape( poly );
193 
194  commit.Add( graphic );
195  }
196 
197  commit.Push( _( "Convert shapes to polygon" ) );
198  }
199  else
200  {
201  // Creating zone or keepout
202  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
203  BOARD_ITEM_CONTAINER* parent = frame->GetModel();
204  ZONE_SETTINGS zoneInfo = frame->GetZoneSettings();
205 
206  bool nonCopper = IsNonCopperLayer( destLayer );
207  zoneInfo.m_Layers.reset().set( destLayer );
208 
209  int ret;
210 
211  if( aEvent.IsAction( &PCB_ACTIONS::convertToKeepout ) )
212  ret = InvokeRuleAreaEditor( frame, &zoneInfo );
213  else if( nonCopper )
214  ret = InvokeNonCopperZonesEditor( frame, &zoneInfo );
215  else
216  ret = InvokeCopperZonesEditor( frame, &zoneInfo );
217 
218  if( ret == wxID_CANCEL )
219  return 0;
220 
221  for( const SHAPE_POLY_SET& poly : polys )
222  {
223  ZONE* zone = isFootprint ? new FP_ZONE( parent ) : new ZONE( parent );
224 
225  *zone->Outline() = poly;
226  zone->HatchBorder();
227 
228  zoneInfo.ExportSetting( *zone );
229 
230  commit.Add( zone );
231  }
232 
233  commit.Push( _( "Convert shapes to zone" ) );
234  }
235 
236  return 0;
237 }
238 
239 
240 SHAPE_POLY_SET CONVERT_TOOL::makePolysFromSegs( const std::deque<EDA_ITEM*>& aItems )
241 {
242  SHAPE_POLY_SET poly;
243 
244  std::map<VECTOR2I, std::vector<EDA_ITEM*>> connections;
245  std::set<EDA_ITEM*> used;
246  std::deque<EDA_ITEM*> toCheck;
247 
248  for( EDA_ITEM* item : aItems )
249  {
250  if( OPT<SEG> seg = getStartEndPoints( item, nullptr ) )
251  {
252  toCheck.push_back( item );
253  connections[seg->A].emplace_back( item );
254  connections[seg->B].emplace_back( item );
255  }
256  }
257 
258  while( !toCheck.empty() )
259  {
260  EDA_ITEM* candidate = toCheck.front();
261  toCheck.pop_front();
262 
263  if( used.count( candidate ) )
264  continue;
265 
266  int width = -1;
267  OPT<SEG> seg = getStartEndPoints( candidate, &width );
268  wxASSERT( seg );
269 
270  SHAPE_LINE_CHAIN outline;
271  std::deque<VECTOR2I> points;
272 
273  // aDirection == true for walking "right" and appending to the end of points
274  // false for walking "left" and prepending to the beginning
275  std::function<void( EDA_ITEM*, bool )> process =
276  [&]( EDA_ITEM* aItem, bool aDirection )
277  {
278  if( used.count( aItem ) )
279  return;
280 
281  used.insert( aItem );
282 
283  OPT<SEG> nextSeg = getStartEndPoints( aItem, &width );
284  wxASSERT( nextSeg );
285 
286  // The reference point, i.e. last added point in the direction we're headed
287  VECTOR2I& ref = aDirection ? points.back() : points.front();
288 
289  // The next point, i.e. the other point on this segment
290  VECTOR2I& next = ( ref == nextSeg->A ) ? nextSeg->B : nextSeg->A;
291 
292  if( aDirection )
293  points.push_back( next );
294  else
295  points.push_front( next );
296 
297  for( EDA_ITEM* neighbor : connections[next] )
298  process( neighbor, aDirection );
299  };
300 
301  // Start with just one point and walk one direction
302  points.push_back( seg->A );
303  process( candidate, true );
304 
305  // check for any candidates on the "left"
306  EDA_ITEM* left = nullptr;
307 
308  for( EDA_ITEM* possibleLeft : connections[seg->A] )
309  {
310  if( possibleLeft != candidate )
311  {
312  left = possibleLeft;
313  break;
314  }
315  }
316 
317  if( left )
318  process( left, false );
319 
320  if( points.size() < 3 )
321  continue;
322 
323  for( const VECTOR2I& point : points )
324  outline.Append( point );
325 
326  outline.SetClosed( true );
327 
328  if( width >= 0 )
329  outline.SetWidth( width );
330 
331  poly.AddOutline( outline );
332  }
333 
334  return poly;
335 }
336 
337 
338 SHAPE_POLY_SET CONVERT_TOOL::makePolysFromRects( const std::deque<EDA_ITEM*>& aItems )
339 {
340  SHAPE_POLY_SET poly;
341 
342  for( EDA_ITEM* item : aItems )
343  {
344  if( item->Type() != PCB_SHAPE_T && item->Type() != PCB_FP_SHAPE_T )
345  continue;
346 
347  PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( item );
348 
349  if( graphic->GetShape() != PCB_SHAPE_TYPE::RECT )
350  continue;
351 
352  SHAPE_LINE_CHAIN outline;
353  VECTOR2I start( graphic->GetStart() );
354  VECTOR2I end( graphic->GetEnd() );
355 
356  outline.Append( start );
357  outline.Append( VECTOR2I( end.x, start.y ) );
358  outline.Append( end );
359  outline.Append( VECTOR2I( start.x, end.y ) );
360  outline.SetClosed( true );
361 
362  outline.SetWidth( graphic->GetWidth() );
363 
364  poly.AddOutline( outline );
365  }
366 
367  return poly;
368 }
369 
370 
371 SHAPE_POLY_SET CONVERT_TOOL::makePolysFromCircles( const std::deque<EDA_ITEM*>& aItems )
372 {
373  SHAPE_POLY_SET poly;
374 
375  for( EDA_ITEM* item : aItems )
376  {
377  if( item->Type() != PCB_SHAPE_T && item->Type() != PCB_FP_SHAPE_T )
378  continue;
379 
380  PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( item );
381 
382  if( graphic->GetShape() != PCB_SHAPE_TYPE::CIRCLE )
383  continue;
384 
385  BOARD_DESIGN_SETTINGS& bds = graphic->GetBoard()->GetDesignSettings();
386  SHAPE_LINE_CHAIN outline;
387 
388  TransformCircleToPolygon( outline, graphic->GetPosition(), graphic->GetRadius(),
389  bds.m_MaxError, ERROR_OUTSIDE );
390 
391  poly.AddOutline( outline );
392  }
393 
394  return poly;
395 }
396 
397 
399 {
400  auto& selection = m_selectionTool->RequestSelection(
401  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
402  {
403  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
404  {
405  BOARD_ITEM* item = aCollector[i];
406 
407  switch( item->Type() )
408  {
409  case PCB_SHAPE_T:
410  case PCB_FP_SHAPE_T:
411  switch( static_cast<PCB_SHAPE*>( item )->GetShape() )
412  {
414  break;
415 
417  break;
418 
419  default:
420  aCollector.Remove( item );
421  }
422 
423  break;
424 
425  case PCB_ZONE_T:
426  case PCB_FP_ZONE_T:
427  break;
428 
429  default:
430  aCollector.Remove( item );
431  }
432  }
433  } );
434 
435  if( selection.Empty() )
436  return 0;
437 
438  auto getPolySet =
439  []( EDA_ITEM* aItem )
440  {
441  SHAPE_POLY_SET set;
442 
443  switch( aItem->Type() )
444  {
445  case PCB_ZONE_T:
446  case PCB_FP_ZONE_T:
447  set = *static_cast<ZONE*>( aItem )->Outline();
448  break;
449 
450  case PCB_SHAPE_T:
451  case PCB_FP_SHAPE_T:
452  {
453  PCB_SHAPE* graphic = static_cast<PCB_SHAPE*>( aItem );
454 
455  if( graphic->GetShape() == PCB_SHAPE_TYPE::POLYGON )
456  {
457  set = graphic->GetPolyShape();
458  }
459  else if( graphic->GetShape() == PCB_SHAPE_TYPE::RECT )
460  {
461  SHAPE_LINE_CHAIN outline;
462  VECTOR2I start( graphic->GetStart() );
463  VECTOR2I end( graphic->GetEnd() );
464 
465  outline.Append( start );
466  outline.Append( VECTOR2I( end.x, start.y ) );
467  outline.Append( end );
468  outline.Append( VECTOR2I( start.x, end.y ) );
469  outline.SetClosed( true );
470 
471  set.AddOutline( outline );
472  }
473  else
474  {
475  wxFAIL_MSG( "Unhandled graphic shape type in PolyToLines - getPolySet" );
476  }
477  break;
478  }
479 
480  default:
481  wxFAIL_MSG( "Unhandled type in PolyToLines - getPolySet" );
482  break;
483  }
484 
485  return set;
486  };
487 
488  auto getSegList =
489  []( SHAPE_POLY_SET& aPoly )
490  {
491  std::vector<SEG> segs;
492 
493  // Our input should be valid polys, so OK to assert here
494  wxASSERT( aPoly.VertexCount() >= 2 );
495 
496  for( int i = 1; i < aPoly.VertexCount(); i++ )
497  segs.emplace_back( SEG( aPoly.CVertex( i - 1 ), aPoly.CVertex( i ) ) );
498 
499  segs.emplace_back( SEG( aPoly.CVertex( aPoly.VertexCount() - 1 ),
500  aPoly.CVertex( 0 ) ) );
501 
502  return segs;
503  };
504 
505  BOARD_COMMIT commit( m_frame );
506  FOOTPRINT_EDIT_FRAME* fpEditor = dynamic_cast<FOOTPRINT_EDIT_FRAME*>( m_frame );
507 
508  FOOTPRINT* footprint = nullptr;
509 
510  if( fpEditor )
511  footprint = fpEditor->GetBoard()->GetFirstFootprint();
512 
513  for( EDA_ITEM* item : selection )
514  {
515  PCB_LAYER_ID layer = static_cast<BOARD_ITEM*>( item )->GetLayer();
516  SHAPE_POLY_SET polySet = getPolySet( item );
517  std::vector<SEG> segs = getSegList( polySet );
518 
519  if( aEvent.IsAction( &PCB_ACTIONS::convertToLines ) )
520  {
521  for( SEG& seg : segs )
522  {
523  if( fpEditor )
524  {
525  FP_SHAPE* graphic = new FP_SHAPE( footprint, PCB_SHAPE_TYPE::SEGMENT );
526 
527  graphic->SetLayer( layer );
528  graphic->SetStart( wxPoint( seg.A ) );
529  graphic->SetStart0( wxPoint( seg.A ) );
530  graphic->SetEnd( wxPoint( seg.B ) );
531  graphic->SetEnd0( wxPoint( seg.B ) );
532  commit.Add( graphic );
533  }
534  else
535  {
536  PCB_SHAPE* graphic = new PCB_SHAPE;
537 
538  graphic->SetShape( PCB_SHAPE_TYPE::SEGMENT );
539  graphic->SetLayer( layer );
540  graphic->SetStart( wxPoint( seg.A ) );
541  graphic->SetEnd( wxPoint( seg.B ) );
542  commit.Add( graphic );
543  }
544  }
545  }
546  else
547  {
548  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
549  BOARD_ITEM_CONTAINER* parent = frame->GetModel();
550 
551  if( !IsCopperLayer( layer ) )
552  layer = frame->SelectOneLayer( F_Cu, LSET::AllNonCuMask() );
553 
554  // I am really unsure converting a polygon to "tracks" (i.e. segments on
555  // copper layers) make sense for footprints, but anyway this code exists
556  if( fpEditor )
557  {
558  // Creating segments on copper layer
559  for( SEG& seg : segs )
560  {
561  FP_SHAPE* graphic = new FP_SHAPE( footprint, PCB_SHAPE_TYPE::SEGMENT );
562  graphic->SetLayer( layer );
563  graphic->SetStart( wxPoint( seg.A ) );
564  graphic->SetStart0( wxPoint( seg.A ) );
565  graphic->SetEnd( wxPoint( seg.B ) );
566  graphic->SetEnd0( wxPoint( seg.B ) );
567  commit.Add( graphic );
568  }
569  }
570  else
571  {
572  // Creating tracks
573  for( SEG& seg : segs )
574  {
575  PCB_TRACK* track = new PCB_TRACK( parent );
576 
577  track->SetLayer( layer );
578  track->SetStart( wxPoint( seg.A ) );
579  track->SetEnd( wxPoint( seg.B ) );
580  commit.Add( track );
581  }
582  }
583  }
584  }
585 
586  commit.Push( _( "Convert polygons to lines" ) );
587 
588  return 0;
589 }
590 
591 
593 {
594  auto& selection = m_selectionTool->RequestSelection(
595  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
596  {
597  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
598  {
599  BOARD_ITEM* item = aCollector[i];
600 
601  if( !( item->Type() == PCB_SHAPE_T ||
602  item->Type() == PCB_TRACE_T ||
603  item->Type() == PCB_FP_SHAPE_T ) )
604  {
605  aCollector.Remove( item );
606  }
607  }
608  } );
609 
610  EDA_ITEM* source = selection.Front();
611  VECTOR2I start, end, mid;
612 
613  // Offset the midpoint along the normal a little bit so that it's more obviously an arc
614  const double offsetRatio = 0.1;
615 
616  if( OPT<SEG> seg = getStartEndPoints( source, nullptr ) )
617  {
618  start = seg->A;
619  end = seg->B;
620 
621  VECTOR2I normal = ( seg->B - seg->A ).Perpendicular().Resize( offsetRatio * seg->Length() );
622  mid = seg->Center() + normal;
623  }
624  else
625  {
626  return -1;
627  }
628 
629  PCB_BASE_EDIT_FRAME* frame = getEditFrame<PCB_BASE_EDIT_FRAME>();
630  BOARD_ITEM_CONTAINER* parent = frame->GetModel();
631 
632  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( source );
633 
634  // Don't continue processing if we don't actually have a board item
635  if( !boardItem )
636  return 0;
637 
638  PCB_LAYER_ID layer = boardItem->GetLayer();
639 
640  BOARD_COMMIT commit( m_frame );
641 
642  if( source->Type() == PCB_SHAPE_T || source->Type() == PCB_FP_SHAPE_T )
643  {
644  PCB_SHAPE* line = static_cast<PCB_SHAPE*>( source );
645  PCB_SHAPE* arc = new PCB_SHAPE( parent );
646 
647  VECTOR2I center = GetArcCenter( start, mid, end );
648 
650  arc->SetFilled( false );
651  arc->SetLayer( layer );
652  arc->SetWidth( line->GetWidth() );
653 
654  arc->SetCenter( wxPoint( center ) );
655  arc->SetArcStart( wxPoint( start ) );
656  arc->SetAngle( GetArcAngle( start, mid, end ) );
657 
658  arc->SetArcEnd( wxPoint( end ) );
659  commit.Add( arc );
660  }
661  else
662  {
663  wxASSERT( source->Type() == PCB_TRACE_T );
664  PCB_TRACK* line = static_cast<PCB_TRACK*>( source );
665  PCB_ARC* arc = new PCB_ARC( parent );
666 
667  arc->SetLayer( layer );
668  arc->SetWidth( line->GetWidth() );
669  arc->SetStart( wxPoint( start ) );
670  arc->SetMid( wxPoint( mid ) );
671  arc->SetEnd( wxPoint( end ) );
672 
673  commit.Add( arc );
674  }
675 
676  commit.Push( _( "Create arc from line segment" ) );
677 
678  return 0;
679 }
680 
681 
683 {
684  switch( aItem->Type() )
685  {
686  case PCB_SHAPE_T:
687  case PCB_FP_SHAPE_T:
688  {
689  PCB_SHAPE* line = static_cast<PCB_SHAPE*>( aItem );
690 
691  if( aWidth )
692  *aWidth = line->GetWidth();
693 
694  return boost::make_optional<SEG>( { VECTOR2I( line->GetStart() ),
695  VECTOR2I( line->GetEnd() ) } );
696  }
697 
698  case PCB_TRACE_T:
699  {
700  PCB_TRACK* line = static_cast<PCB_TRACK*>( aItem );
701 
702  if( aWidth )
703  *aWidth = line->GetWidth();
704 
705  return boost::make_optional<SEG>( { VECTOR2I( line->GetStart() ),
706  VECTOR2I( line->GetEnd() ) } );
707  }
708 
709  case PCB_ARC_T:
710  {
711  PCB_ARC* arc = static_cast<PCB_ARC*>( aItem );
712 
713  if( aWidth )
714  *aWidth = arc->GetWidth();
715 
716  return boost::make_optional<SEG>( { VECTOR2I( arc->GetStart() ),
717  VECTOR2I( arc->GetEnd() ) } );
718  }
719 
720  default:
721  return NULLOPT;
722  }
723 }
724 
725 
727 {
734 }
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
static OPT< SEG > getStartEndPoints(EDA_ITEM *aItem, int *aWidth)
Retrieve the start and end points for a generic item.
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:478
SHAPE_POLY_SET & GetPolyShape()
Definition: pcb_shape.h:239
const wxPoint & GetEnd() const
Definition: pcb_track.h:105
static TOOL_ACTION convertToLines
Definition: pcb_actions.h:476
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: pcb_shape.h:134
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:192
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:80
void SetIcon(BITMAPS aIcon)
Assign an icon for the entry.
Definition: action_menu.cpp:73
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...
void SetEnd(const wxPoint &aEnd)
Definition: pcb_track.h:104
COMMIT & Add(EDA_ITEM *aItem)
Notify observers that aItem has been added.
Definition: commit.h:78
PCB_SHAPE_TYPE GetShape() const
Definition: pcb_shape.h:110
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:73
int InvokeNonCopperZonesEditor(PCB_BASE_FRAME *aParent, ZONE_SETTINGS *aSettings)
Function InvokeNonCopperZonesEditor invokes up a modal dialog window for non-copper zone editing.
SHAPE_POLY_SET * Outline()
Definition: zone.h:317
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:46
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:445
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
bool IsEmpty() const
int GetWidth() const
Definition: pcb_shape.h:97
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition: lset.cpp:773
static SHAPE_POLY_SET makePolysFromCircles(const std::deque< EDA_ITEM * > &aItems)
Try to make polygons from circles.
TOOL_MENU & GetToolMenu()
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
Class that groups generic conditions for selected items.
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
int GetWidth() const
Definition: pcb_track.h:102
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
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
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 PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
bool IsNonCopperLayer(LAYER_NUM aLayerId)
Test whether a layer is a non copper layer.
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:88
virtual ~CONVERT_TOOL()
polygon (not yet used for tracks, but could be in microwave apps)
virtual PCB_LAYER_ID GetActiveLayer() const
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 SetWidth(int aWidth)
Sets the width of all segments in the chain.
void SetClosed(bool aClosed)
Function SetClosed()
PCB_LAYER_ID
A quick note on layer IDs:
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Definition: board.h:317
const auto NULLOPT
Definition: optional.h:9
#define NULL
void ExportSetting(ZONE &aTarget, bool aFullExport=true) const
Function ExportSetting copy settings to a given zone.
void HatchBorder()
Compute the hatch lines depending on the hatch parameters and stores it in the zone's attribute m_bor...
Definition: zone.cpp:929
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
void SetMid(const wxPoint &aMid)
Definition: pcb_track.h:272
segment with non rounded ends
const ZONE_SETTINGS & GetZoneSettings() const
Generic, UI-independent tool event.
Definition: tool_event.h:152
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: pcb_shape.h:124
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:50
static TOOL_ACTION convertToZone
Definition: pcb_actions.h:474
void SetStart(const wxPoint &aStart)
Definition: pcb_track.h:107
static TOOL_ACTION convertToKeepout
Definition: pcb_actions.h:475
#define _(s)
Handle 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)
Definition: pcb_shape.h:199
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:40
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:70
PCB_BASE_FRAME * m_frame
Definition: convert_tool.h:105
void SetWidth(int aWidth)
Definition: pcb_track.h:101
static TOOL_ACTION convertToArc
Definition: pcb_actions.h:477
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:91
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.
void SetStart(const wxPoint &aStart)
Definition: pcb_shape.h:127
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
SHAPE_LINE_CHAIN.
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
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)
usual segment : line with rounded ends
void SetWidth(int aWidth)
Definition: pcb_shape.h:96
The selection tool: currently supports:
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
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.
void SetArcEnd(const wxPoint &aArcEndPoint)
Initialize the end arc point.
Definition: pcb_shape.h:194
boost::optional< T > OPT
Definition: optional.h:7
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.
static TOOL_ACTION convertToPoly
Definition: pcb_actions.h:473
void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition: pcb_shape.h:247
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.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
BOARD * GetBoard() const
static SELECTION_CONDITION OnlyGraphicShapeTypes(const std::set< PCB_SHAPE_TYPE > aTypes)
Create a functor that tests if the selection contains PCB_SHAPE* items of certain shapes.
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
void SetShape(PCB_SHAPE_TYPE aShape)
Definition: pcb_shape.h:109
Arcs (with rounded ends)
virtual void SetAngle(double aAngle, bool aUpdateEnd=true)
Set the angle for arcs, and normalizes it within the range 0 - 360 degrees.
Definition: pcb_shape.cpp:477
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:171
A specialization of ZONE for use in footprints.
Definition: zone.h:943
const wxPoint & GetStart() const
Definition: pcb_track.h:108
void SetEnd(const wxPoint &aEnd)
Definition: pcb_shape.h:137
void SetArcStart(const wxPoint &aArcStartPoint)
Initialize the start arc point.
Definition: pcb_shape.h:184
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
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...