KiCad PCB EDA Suite
footprint.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 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2015 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
7  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <core/mirror.h>
28 #include <confirm.h>
29 #include <refdes_utils.h>
30 #include <bitmaps.h>
31 #include <unordered_set>
32 #include <string_utils.h>
33 #include <pcb_edit_frame.h>
34 #include <board.h>
35 #include <board_design_settings.h>
36 #include <fp_shape.h>
37 #include <macros.h>
38 #include <pad.h>
39 #include <pcb_text.h>
40 #include <pcb_marker.h>
41 #include <pcb_group.h>
42 #include <pcb_track.h>
43 #include <footprint.h>
44 #include <zone.h>
45 #include <view/view.h>
46 #include <geometry/shape_null.h>
47 #include <i18n_utility.h>
49 #include <geometry/convex_hull.h>
50 
53  m_boundingBoxCacheTimeStamp( 0 ),
54  m_visibleBBoxCacheTimeStamp( 0 ),
55  m_textExcludedBBoxCacheTimeStamp( 0 ),
56  m_hullCacheTimeStamp( 0 ),
57  m_initial_comments( nullptr )
58 {
59  m_attributes = 0;
60  m_layer = F_Cu;
61  m_orient = 0;
63  m_arflag = 0;
65  m_link = 0;
66  m_lastEditTime = 0;
67  m_localClearance = 0;
71  m_zoneConnection = ZONE_CONNECTION::INHERITED; // Use zone setting by default
72  m_thermalWidth = 0; // Use zone setting by default
73  m_thermalGap = 0; // Use zone setting by default
74 
75  // These are special and mandatory text fields
77  m_value = new FP_TEXT( this, FP_TEXT::TEXT_is_VALUE );
78 
79  m_3D_Drawings.clear();
80 }
81 
82 
83 FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
84  BOARD_ITEM_CONTAINER( aFootprint )
85 {
86  m_pos = aFootprint.m_pos;
87  m_fpid = aFootprint.m_fpid;
88  m_attributes = aFootprint.m_attributes;
89  m_fpStatus = aFootprint.m_fpStatus;
90  m_orient = aFootprint.m_orient;
91  m_rot90Cost = aFootprint.m_rot90Cost;
92  m_rot180Cost = aFootprint.m_rot180Cost;
93  m_lastEditTime = aFootprint.m_lastEditTime;
94  m_link = aFootprint.m_link;
95  m_path = aFootprint.m_path;
96 
103  m_cachedHull = aFootprint.m_cachedHull;
105 
106  m_localClearance = aFootprint.m_localClearance;
110  m_zoneConnection = aFootprint.m_zoneConnection;
111  m_thermalWidth = aFootprint.m_thermalWidth;
112  m_thermalGap = aFootprint.m_thermalGap;
113 
114  std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
115 
116  // Copy reference and value.
117  m_reference = new FP_TEXT( *aFootprint.m_reference );
118  m_reference->SetParent( this );
119  ptrMap[ aFootprint.m_reference ] = m_reference;
120 
121  m_value = new FP_TEXT( *aFootprint.m_value );
122  m_value->SetParent( this );
123  ptrMap[ aFootprint.m_value ] = m_value;
124 
125  // Copy pads
126  for( PAD* pad : aFootprint.Pads() )
127  {
128  PAD* newPad = static_cast<PAD*>( pad->Clone() );
129  ptrMap[ pad ] = newPad;
130  Add( newPad, ADD_MODE::APPEND ); // Append to ensure indexes are identical
131  }
132 
133  // Copy zones
134  for( FP_ZONE* zone : aFootprint.Zones() )
135  {
136  FP_ZONE* newZone = static_cast<FP_ZONE*>( zone->Clone() );
137  ptrMap[ zone ] = newZone;
138  Add( newZone, ADD_MODE::APPEND ); // Append to ensure indexes are identical
139 
140  // Ensure the net info is OK and especially uses the net info list
141  // living in the current board
142  // Needed when copying a fp from fp editor that has its own board
143  // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
144  newZone->SetNetCode( -1 );
145  }
146 
147  // Copy drawings
148  for( BOARD_ITEM* item : aFootprint.GraphicalItems() )
149  {
150  BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
151  ptrMap[ item ] = newItem;
152  Add( newItem, ADD_MODE::APPEND ); // Append to ensure indexes are identical
153  }
154 
155  // Copy groups
156  for( PCB_GROUP* group : aFootprint.Groups() )
157  {
158  PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
159  ptrMap[ group ] = newGroup;
160  Add( newGroup, ADD_MODE::APPEND ); // Append to ensure indexes are identical
161  }
162 
163  // Rebuild groups
164  for( PCB_GROUP* group : aFootprint.Groups() )
165  {
166  PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( ptrMap[ group ] );
167 
168  newGroup->GetItems().clear();
169 
170  for( BOARD_ITEM* member : group->GetItems() )
171  {
172  if( ptrMap.count( member ) )
173  newGroup->AddItem( ptrMap[ member ] );
174  }
175  }
176 
177  // Copy auxiliary data: 3D_Drawings info
178  m_3D_Drawings = aFootprint.m_3D_Drawings;
179 
180  m_doc = aFootprint.m_doc;
181  m_keywords = aFootprint.m_keywords;
182  m_properties = aFootprint.m_properties;
183 
184  m_arflag = 0;
185 
187  new wxArrayString( *aFootprint.m_initial_comments ) : nullptr;
188 }
189 
190 
192  BOARD_ITEM_CONTAINER( aFootprint )
193 {
194  *this = std::move( aFootprint );
195 }
196 
197 
199 {
200  // Clean up the owned elements
201  delete m_reference;
202  delete m_value;
203  delete m_initial_comments;
204 
205  for( PAD* p : m_pads )
206  delete p;
207 
208  m_pads.clear();
209 
210  for( FP_ZONE* zone : m_fp_zones )
211  delete zone;
212 
213  m_fp_zones.clear();
214 
215  for( PCB_GROUP* group : m_fp_groups )
216  delete group;
217 
218  m_fp_groups.clear();
219 
220  for( BOARD_ITEM* d : m_drawings )
221  delete d;
222 
223  m_drawings.clear();
224 }
225 
226 
228 {
229  // replace null UUIDs if any by a valid uuid
230  std::vector< BOARD_ITEM* > item_list;
231 
232  item_list.push_back( m_reference );
233  item_list.push_back( m_value );
234 
235  for( PAD* pad : m_pads )
236  item_list.push_back( pad );
237 
238  for( BOARD_ITEM* gr_item : m_drawings )
239  item_list.push_back( gr_item );
240 
241  // Note: one cannot fix null UUIDs inside the group, but it should not happen
242  // because null uuids can be found in old footprints, therefore without group
243  for( PCB_GROUP* group : m_fp_groups )
244  item_list.push_back( group );
245 
246  // Probably notneeded, because old fp do not have zones. But just in case.
247  for( FP_ZONE* zone : m_fp_zones )
248  item_list.push_back( zone );
249 
250  bool changed = false;
251 
252  for( BOARD_ITEM* item : item_list )
253  {
254  if( item->m_Uuid == niluuid )
255  {
256  const_cast<KIID&>( item->m_Uuid ) = KIID();
257  changed = true;
258  }
259  }
260 
261  return changed;
262 }
263 
264 
266 {
267  BOARD_ITEM::operator=( aOther );
268 
269  m_pos = aOther.m_pos;
270  m_fpid = aOther.m_fpid;
271  m_attributes = aOther.m_attributes;
272  m_fpStatus = aOther.m_fpStatus;
273  m_orient = aOther.m_orient;
274  m_rot90Cost = aOther.m_rot90Cost;
275  m_rot180Cost = aOther.m_rot180Cost;
276  m_lastEditTime = aOther.m_lastEditTime;
277  m_link = aOther.m_link;
278  m_path = aOther.m_path;
279 
280  m_cachedBoundingBox = aOther.m_cachedBoundingBox;
281  m_boundingBoxCacheTimeStamp = aOther.m_boundingBoxCacheTimeStamp;
282  m_cachedVisibleBBox = aOther.m_cachedVisibleBBox;
283  m_visibleBBoxCacheTimeStamp = aOther.m_visibleBBoxCacheTimeStamp;
284  m_cachedTextExcludedBBox = aOther.m_cachedTextExcludedBBox;
285  m_textExcludedBBoxCacheTimeStamp = aOther.m_textExcludedBBoxCacheTimeStamp;
286  m_cachedHull = aOther.m_cachedHull;
287  m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp;
288 
289  m_localClearance = aOther.m_localClearance;
290  m_localSolderMaskMargin = aOther.m_localSolderMaskMargin;
291  m_localSolderPasteMargin = aOther.m_localSolderPasteMargin;
292  m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio;
293  m_zoneConnection = aOther.m_zoneConnection;
294  m_thermalWidth = aOther.m_thermalWidth;
295  m_thermalGap = aOther.m_thermalGap;
296 
297  // Move reference and value
298  m_reference = aOther.m_reference;
299  m_reference->SetParent( this );
300  m_value = aOther.m_value;
301  m_value->SetParent( this );
302 
303 
304  // Move the pads
305  m_pads.clear();
306 
307  for( PAD* pad : aOther.Pads() )
308  Add( pad );
309 
310  aOther.Pads().clear();
311 
312  // Move the zones
313  m_fp_zones.clear();
314 
315  for( FP_ZONE* item : aOther.Zones() )
316  {
317  Add( item );
318 
319  // Ensure the net info is OK and especially uses the net info list
320  // living in the current board
321  // Needed when copying a fp from fp editor that has its own board
322  // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
323  item->SetNetCode( -1 );
324  }
325 
326  aOther.Zones().clear();
327 
328  // Move the drawings
329  m_drawings.clear();
330 
331  for( BOARD_ITEM* item : aOther.GraphicalItems() )
332  Add( item );
333 
334  aOther.GraphicalItems().clear();
335 
336  // Move the groups
337  m_fp_groups.clear();
338 
339  for( PCB_GROUP* group : aOther.Groups() )
340  Add( group );
341 
342  aOther.Groups().clear();
343 
344  // Copy auxiliary data: 3D_Drawings info
345  m_3D_Drawings.clear();
346  m_3D_Drawings = aOther.m_3D_Drawings;
347  m_doc = aOther.m_doc;
348  m_keywords = aOther.m_keywords;
349  m_properties = aOther.m_properties;
350 
351  m_initial_comments = aOther.m_initial_comments;
352 
353  // Clear the other item's containers since this is a move
354  aOther.Pads().clear();
355  aOther.Zones().clear();
356  aOther.GraphicalItems().clear();
357  aOther.m_value = nullptr;
358  aOther.m_reference = nullptr;
359  aOther.m_initial_comments = nullptr;
360 
361  return *this;
362 }
363 
364 
366 {
367  BOARD_ITEM::operator=( aOther );
368 
369  m_pos = aOther.m_pos;
370  m_fpid = aOther.m_fpid;
371  m_attributes = aOther.m_attributes;
372  m_fpStatus = aOther.m_fpStatus;
373  m_orient = aOther.m_orient;
374  m_rot90Cost = aOther.m_rot90Cost;
375  m_rot180Cost = aOther.m_rot180Cost;
377  m_link = aOther.m_link;
378  m_path = aOther.m_path;
379 
386  m_cachedHull = aOther.m_cachedHull;
388 
395  m_thermalGap = aOther.m_thermalGap;
396 
397  // Copy reference and value
398  *m_reference = *aOther.m_reference;
399  m_reference->SetParent( this );
400  *m_value = *aOther.m_value;
401  m_value->SetParent( this );
402 
403  std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
404 
405  // Copy pads
406  m_pads.clear();
407 
408  for( PAD* pad : aOther.Pads() )
409  {
410  PAD* newPad = new PAD( *pad );
411  ptrMap[ pad ] = newPad;
412  Add( newPad );
413  }
414 
415  // Copy zones
416  m_fp_zones.clear();
417 
418  for( FP_ZONE* zone : aOther.Zones() )
419  {
420  FP_ZONE* newZone = static_cast<FP_ZONE*>( zone->Clone() );
421  ptrMap[ zone ] = newZone;
422  Add( newZone );
423 
424  // Ensure the net info is OK and especially uses the net info list
425  // living in the current board
426  // Needed when copying a fp from fp editor that has its own board
427  // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
428  newZone->SetNetCode( -1 );
429  }
430 
431  // Copy drawings
432  m_drawings.clear();
433 
434  for( BOARD_ITEM* item : aOther.GraphicalItems() )
435  {
436  BOARD_ITEM* newItem = static_cast<BOARD_ITEM*>( item->Clone() );
437  ptrMap[ item ] = newItem;
438  Add( newItem );
439  }
440 
441  // Copy groups
442  m_fp_groups.clear();
443 
444  for( PCB_GROUP* group : aOther.Groups() )
445  {
446  PCB_GROUP* newGroup = static_cast<PCB_GROUP*>( group->Clone() );
447  newGroup->GetItems().clear();
448 
449  for( BOARD_ITEM* member : group->GetItems() )
450  newGroup->AddItem( ptrMap[ member ] );
451 
452  Add( newGroup );
453  }
454 
455  // Copy auxiliary data: 3D_Drawings info
456  m_3D_Drawings.clear();
457  m_3D_Drawings = aOther.m_3D_Drawings;
458  m_doc = aOther.m_doc;
459  m_keywords = aOther.m_keywords;
460  m_properties = aOther.m_properties;
461 
463  new wxArrayString( *aOther.m_initial_comments ) : nullptr;
464 
465  return *this;
466 }
467 
468 
469 void FOOTPRINT::GetContextualTextVars( wxArrayString* aVars ) const
470 {
471  aVars->push_back( wxT( "REFERENCE" ) );
472  aVars->push_back( wxT( "VALUE" ) );
473  aVars->push_back( wxT( "LAYER" ) );
474 }
475 
476 
477 bool FOOTPRINT::ResolveTextVar( wxString* token, int aDepth ) const
478 {
479  if( token->IsSameAs( wxT( "REFERENCE" ) ) )
480  {
481  *token = m_reference->GetShownText( aDepth + 1 );
482  return true;
483  }
484  else if( token->IsSameAs( wxT( "VALUE" ) ) )
485  {
486  *token = m_value->GetShownText( aDepth + 1 );
487  return true;
488  }
489  else if( token->IsSameAs( wxT( "LAYER" ) ) )
490  {
491  *token = GetLayerName();
492  return true;
493  }
494  else if( m_properties.count( *token ) )
495  {
496  *token = m_properties.at( *token );
497  return true;
498  }
499 
500  return false;
501 }
502 
503 
505 {
506  // Force the ORPHANED dummy net info for all pads.
507  // ORPHANED dummy net does not depend on a board
508  for( PAD* pad : m_pads )
509  pad->SetNetCode( NETINFO_LIST::ORPHANED );
510 }
511 
512 
513 void FOOTPRINT::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
514 {
515  switch( aBoardItem->Type() )
516  {
517  case PCB_FP_TEXT_T:
518  // Only user text can be added this way.
519  wxASSERT( static_cast<FP_TEXT*>( aBoardItem )->GetType() == FP_TEXT::TEXT_is_DIVERS );
521 
522  case PCB_FP_SHAPE_T:
523  if( aMode == ADD_MODE::APPEND )
524  m_drawings.push_back( aBoardItem );
525  else
526  m_drawings.push_front( aBoardItem );
527  break;
528 
529  case PCB_PAD_T:
530  if( aMode == ADD_MODE::APPEND )
531  m_pads.push_back( static_cast<PAD*>( aBoardItem ) );
532  else
533  m_pads.push_front( static_cast<PAD*>( aBoardItem ) );
534  break;
535 
536  case PCB_FP_ZONE_T:
537  if( aMode == ADD_MODE::APPEND )
538  m_fp_zones.push_back( static_cast<FP_ZONE*>( aBoardItem ) );
539  else
540  m_fp_zones.insert( m_fp_zones.begin(), static_cast<FP_ZONE*>( aBoardItem ) );
541  break;
542 
543  case PCB_GROUP_T:
544  if( aMode == ADD_MODE::APPEND )
545  m_fp_groups.push_back( static_cast<PCB_GROUP*>( aBoardItem ) );
546  else
547  m_fp_groups.insert( m_fp_groups.begin(), static_cast<PCB_GROUP*>( aBoardItem ) );
548  break;
549 
550  default:
551  {
552  wxString msg;
553  msg.Printf( wxT( "FOOTPRINT::Add() needs work: BOARD_ITEM type (%d) not handled" ),
554  aBoardItem->Type() );
555  wxFAIL_MSG( msg );
556 
557  return;
558  }
559  }
560 
561  aBoardItem->ClearEditFlags();
562  aBoardItem->SetParent( this );
563 }
564 
565 
566 void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode )
567 {
568  switch( aBoardItem->Type() )
569  {
570  case PCB_FP_TEXT_T:
571  // Only user text can be removed this way.
572  wxCHECK_RET(
573  static_cast<FP_TEXT*>( aBoardItem )->GetType() == FP_TEXT::TEXT_is_DIVERS,
574  "Please report this bug: Invalid remove operation on required text" );
576 
577  case PCB_FP_SHAPE_T:
578  for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
579  {
580  if( *it == aBoardItem )
581  {
582  m_drawings.erase( it );
583  break;
584  }
585  }
586 
587  break;
588 
589  case PCB_PAD_T:
590  for( auto it = m_pads.begin(); it != m_pads.end(); ++it )
591  {
592  if( *it == static_cast<PAD*>( aBoardItem ) )
593  {
594  m_pads.erase( it );
595  break;
596  }
597  }
598 
599  break;
600 
601  case PCB_FP_ZONE_T:
602  for( auto it = m_fp_zones.begin(); it != m_fp_zones.end(); ++it )
603  {
604  if( *it == static_cast<FP_ZONE*>( aBoardItem ) )
605  {
606  m_fp_zones.erase( it );
607  break;
608  }
609  }
610 
611  break;
612 
613  case PCB_GROUP_T:
614  for( auto it = m_fp_groups.begin(); it != m_fp_groups.end(); ++it )
615  {
616  if( *it == static_cast<PCB_GROUP*>( aBoardItem ) )
617  {
618  m_fp_groups.erase( it );
619  break;
620  }
621  }
622 
623  break;
624 
625  default:
626  {
627  wxString msg;
628  msg.Printf( wxT( "FOOTPRINT::Remove() needs work: BOARD_ITEM type (%d) not handled" ),
629  aBoardItem->Type() );
630  wxFAIL_MSG( msg );
631  }
632  }
633 
634  aBoardItem->SetFlags( STRUCT_DELETED );
635 
636  PCB_GROUP* parentGroup = aBoardItem->GetParentGroup();
637 
638  if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
639  parentGroup->RemoveItem( aBoardItem );
640 }
641 
642 
643 double FOOTPRINT::GetArea( int aPadding ) const
644 {
645  EDA_RECT bbox = GetBoundingBox( false, false );
646 
647  double w = std::abs( static_cast<double>( bbox.GetWidth() ) ) + aPadding;
648  double h = std::abs( static_cast<double>( bbox.GetHeight() ) ) + aPadding;
649  return w * h;
650 }
651 
652 
654 {
655  EDA_RECT area;
656 
657  // We want the bounding box of the footprint pads at rot 0, not flipped
658  // Create such a image:
659  FOOTPRINT dummy( *this );
660 
661  dummy.SetPosition( wxPoint( 0, 0 ) );
662 
663  if( dummy.IsFlipped() )
664  dummy.Flip( wxPoint( 0, 0 ) , false );
665 
666  if( dummy.GetOrientation() )
667  dummy.SetOrientation( 0 );
668 
669  for( PAD* pad : dummy.Pads() )
670  area.Merge( pad->GetBoundingBox() );
671 
672  return area;
673 }
674 
675 
677 {
678  return GetBoundingBox( true, true );
679 }
680 
681 
682 const EDA_RECT FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const
683 {
684  const BOARD* board = GetBoard();
685 
686  if( board )
687  {
688  if( aIncludeText && aIncludeInvisibleText )
689  {
690  if( m_boundingBoxCacheTimeStamp >= board->GetTimeStamp() )
691  return m_cachedBoundingBox;
692  }
693  else if( aIncludeText )
694  {
695  if( m_visibleBBoxCacheTimeStamp >= board->GetTimeStamp() )
696  return m_cachedVisibleBBox;
697  }
698  else
699  {
702  }
703  }
704 
705  EDA_RECT area;
706 
707  area.SetOrigin( m_pos );
708  area.SetEnd( m_pos );
709  area.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the area
710 
711  for( BOARD_ITEM* item : m_drawings )
712  {
713  if( item->Type() == PCB_FP_SHAPE_T )
714  area.Merge( item->GetBoundingBox() );
715  }
716 
717  for( PAD* pad : m_pads )
718  area.Merge( pad->GetBoundingBox() );
719 
720  for( FP_ZONE* zone : m_fp_zones )
721  area.Merge( zone->GetBoundingBox() );
722 
723  bool noDrawItems = ( m_drawings.empty() && m_pads.empty() && m_fp_zones.empty() );
724 
725  // Groups do not contribute to the rect, only their members
726  if( aIncludeText || noDrawItems )
727  {
728  for( BOARD_ITEM* item : m_drawings )
729  {
730  if( item->Type() == PCB_FP_TEXT_T )
731  area.Merge( item->GetBoundingBox() );
732  }
733 
734  // This can be further optimized when aIncludeInvisibleText is true, but currently
735  // leaving this as is until it's determined there is a noticeable speed hit.
736  bool valueLayerIsVisible = true;
737  bool refLayerIsVisible = true;
738 
739  if( board )
740  {
741  // The first "&&" conditional handles the user turning layers off as well as layers
742  // not being present in the current PCB stackup. Values, references, and all
743  // footprint text can also be turned off via the GAL meta-layers, so the 2nd and
744  // 3rd "&&" conditionals handle that.
745  valueLayerIsVisible = board->IsLayerVisible( m_value->GetLayer() )
747  && board->IsElementVisible( LAYER_MOD_TEXT_FR );
748 
749  refLayerIsVisible = board->IsLayerVisible( m_reference->GetLayer() )
751  && board->IsElementVisible( LAYER_MOD_TEXT_FR );
752  }
753 
754 
755  if( ( m_value->IsVisible() && valueLayerIsVisible )
756  || aIncludeInvisibleText || noDrawItems )
757  area.Merge( m_value->GetBoundingBox() );
758 
759  if( ( m_reference->IsVisible() && refLayerIsVisible )
760  || aIncludeInvisibleText || noDrawItems )
761  area.Merge( m_reference->GetBoundingBox() );
762  }
763 
764  if( board )
765  {
766  if( ( aIncludeText && aIncludeInvisibleText ) || noDrawItems )
767  {
769  m_cachedBoundingBox = area;
770  }
771  else if( aIncludeText )
772  {
774  m_cachedVisibleBBox = area;
775  }
776  else
777  {
780  }
781  }
782 
783  return area;
784 }
785 
786 
788 {
789  const BOARD* board = GetBoard();
790 
791  if( board )
792  {
793  if( m_hullCacheTimeStamp >= board->GetTimeStamp() )
794  return m_cachedHull;
795  }
796 
797  SHAPE_POLY_SET rawPolys;
798  SHAPE_POLY_SET hull;
799 
800  for( BOARD_ITEM* item : m_drawings )
801  {
802  if( item->Type() == PCB_FP_SHAPE_T )
803  {
804  item->TransformShapeWithClearanceToPolygon( rawPolys, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
805  ERROR_OUTSIDE );
806  }
807 
808  // We intentionally exclude footprint text from the bounding hull.
809  }
810 
811  for( PAD* pad : m_pads )
812  {
813  pad->TransformShapeWithClearanceToPolygon( rawPolys, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
814  ERROR_OUTSIDE );
815  }
816 
817  for( FP_ZONE* zone : m_fp_zones )
818  {
819  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
820  {
821  SHAPE_POLY_SET layerPoly = zone->GetFilledPolysList( layer );
822 
823  for( int ii = 0; ii < layerPoly.OutlineCount(); ii++ )
824  {
825  const SHAPE_LINE_CHAIN& poly = layerPoly.COutline( ii );
826  rawPolys.AddOutline( poly );
827  }
828  }
829  }
830 
831  // If there are some graphic items, build the actual hull.
832  // However if no items, create a minimal polygon (can happen if a footprint
833  // is created with no item: it contains only 2 texts.
834  if( rawPolys.OutlineCount() == 0 )
835  {
836  // generate a small dummy rectangular outline around the anchor
837  const int halfsize = Millimeter2iu( 1.0 );
838 
839  rawPolys.NewOutline();
840 
841  // add a square:
842  rawPolys.Append( GetPosition().x - halfsize, GetPosition().y - halfsize );
843  rawPolys.Append( GetPosition().x + halfsize, GetPosition().y - halfsize );
844  rawPolys.Append( GetPosition().x + halfsize, GetPosition().y + halfsize );
845  rawPolys.Append( GetPosition().x - halfsize, GetPosition().y + halfsize );
846  }
847 
848  std::vector<wxPoint> convex_hull;
849  BuildConvexHull( convex_hull, rawPolys );
850 
853 
854  for( const wxPoint& pt : convex_hull )
855  m_cachedHull.Append( pt );
856 
857  if( board )
859 
860  return m_cachedHull;
861 }
862 
863 
864 void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
865 {
866  wxString msg, msg2;
867 
868  aList.emplace_back( m_reference->GetShownText(), m_value->GetShownText() );
869 
870  if( aFrame->IsType( FRAME_FOOTPRINT_VIEWER )
872  || aFrame->IsType( FRAME_FOOTPRINT_EDITOR ) )
873  {
874  wxDateTime date( static_cast<time_t>( m_lastEditTime ) );
875 
876  // Date format: see http://www.cplusplus.com/reference/ctime/strftime
877  if( m_lastEditTime && date.IsValid() )
878  msg = date.Format( wxT( "%b %d, %Y" ) ); // Abbreviated_month_name Day, Year
879  else
880  msg = _( "Unknown" );
881 
882  aList.emplace_back( _( "Last Change" ), msg );
883  }
884  else if( aFrame->IsType( FRAME_PCB_EDITOR ) )
885  {
886  aList.emplace_back( _( "Board Side" ), IsFlipped() ? _( "Back (Flipped)" ) : _( "Front" ) );
887  }
888 
889  auto addToken = []( wxString* aStr, const wxString& aAttr )
890  {
891  if( !aStr->IsEmpty() )
892  *aStr += wxT( ", " );
893 
894  *aStr += aAttr;
895  };
896 
897  wxString status;
898  wxString attrs;
899 
900  if( IsLocked() )
901  addToken( &status, _( "Locked" ) );
902 
903  if( m_fpStatus & FP_is_PLACED )
904  addToken( &status, _( "autoplaced" ) );
905 
907  addToken( &attrs, _( "not in schematic" ) );
908 
910  addToken( &attrs, _( "exclude from pos files" ) );
911 
913  addToken( &attrs, _( "exclude from BOM" ) );
914 
915  aList.emplace_back( _( "Status: " ) + status, _( "Attributes:" ) + wxS( " " ) + attrs );
916 
917  aList.emplace_back( _( "Rotation" ), wxString::Format( "%.4g", GetOrientationDegrees() ) );
918 
919  msg.Printf( _( "Footprint: %s" ), m_fpid.Format().c_str() );
920  msg2.Printf( _( "3D-Shape: %s" ), m_3D_Drawings.empty() ? _( "<none>" )
921  : m_3D_Drawings.front().m_Filename );
922  aList.emplace_back( msg, msg2 );
923 
924  msg.Printf( _( "Doc: %s" ), m_doc );
925  msg2.Printf( _( "Keywords: %s" ), m_keywords );
926  aList.emplace_back( msg, msg2 );
927 }
928 
929 
930 bool FOOTPRINT::IsOnLayer( PCB_LAYER_ID aLayer ) const
931 {
932  // If we have any pads, fall back on normal checking
933  if( !m_pads.empty() )
934  return m_layer == aLayer;
935 
936  // No pads? Check if this entire footprint exists on the given layer
937  for( FP_ZONE* zone : m_fp_zones )
938  {
939  if( !zone->IsOnLayer( aLayer ) )
940  return false;
941  }
942 
943  for( BOARD_ITEM* item : m_drawings )
944  {
945  if( !item->IsOnLayer( aLayer ) )
946  return false;
947  }
948 
949  return true;
950 }
951 
952 
953 bool FOOTPRINT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
954 {
955  EDA_RECT rect = GetBoundingBox( false, false );
956  return rect.Inflate( aAccuracy ).Contains( aPosition );
957 }
958 
959 
960 bool FOOTPRINT::HitTestAccurate( const wxPoint& aPosition, int aAccuracy ) const
961 {
962  return GetBoundingHull().Collide( aPosition, aAccuracy );
963 }
964 
965 
966 bool FOOTPRINT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
967 {
968  EDA_RECT arect = aRect;
969  arect.Inflate( aAccuracy );
970 
971  if( aContained )
972  {
973  return arect.Contains( GetBoundingBox( false, false ) );
974  }
975  else
976  {
977  // If the rect does not intersect the bounding box, skip any tests
978  if( !aRect.Intersects( GetBoundingBox( false, false ) ) )
979  return false;
980 
981  // The empty footprint dummy rectangle intersects the selection area.
982  if( m_pads.empty() && m_fp_zones.empty() && m_drawings.empty() )
983  return GetBoundingBox( true, false ).Intersects( arect );
984 
985  // Determine if any elements in the FOOTPRINT intersect the rect
986  for( PAD* pad : m_pads )
987  {
988  if( pad->HitTest( arect, false, 0 ) )
989  return true;
990  }
991 
992  for( FP_ZONE* zone : m_fp_zones )
993  {
994  if( zone->HitTest( arect, false, 0 ) )
995  return true;
996  }
997 
998  for( BOARD_ITEM* item : m_drawings )
999  {
1000  if( item->Type() != PCB_FP_TEXT_T && item->HitTest( arect, false, 0 ) )
1001  return true;
1002  }
1003 
1004  // Groups are not hit-tested; only their members
1005 
1006  // No items were hit
1007  return false;
1008  }
1009 }
1010 
1011 
1012 PAD* FOOTPRINT::FindPadByNumber( const wxString& aPadNumber, PAD* aSearchAfterMe ) const
1013 {
1014  bool can_select = aSearchAfterMe ? false : true;
1015 
1016  for( PAD* pad : m_pads )
1017  {
1018  if( !can_select && pad == aSearchAfterMe )
1019  {
1020  can_select = true;
1021  continue;
1022  }
1023 
1024  if( can_select && pad->GetNumber() == aPadNumber )
1025  return pad;
1026  }
1027 
1028  return nullptr;
1029 }
1030 
1031 
1032 PAD* FOOTPRINT::GetPad( const wxPoint& aPosition, LSET aLayerMask )
1033 {
1034  for( PAD* pad : m_pads )
1035  {
1036  // ... and on the correct layer.
1037  if( !( pad->GetLayerSet() & aLayerMask ).any() )
1038  continue;
1039 
1040  if( pad->HitTest( aPosition ) )
1041  return pad;
1042  }
1043 
1044  return nullptr;
1045 }
1046 
1047 
1049 {
1050  PAD* topLeftPad = m_pads.front();
1051 
1052  for( PAD* p : m_pads )
1053  {
1054  wxPoint pnt = p->GetPosition(); // GetPosition() returns the center of the pad
1055 
1056  if( ( pnt.x < topLeftPad->GetPosition().x ) ||
1057  ( topLeftPad->GetPosition().x == pnt.x && pnt.y < topLeftPad->GetPosition().y ) )
1058  {
1059  topLeftPad = p;
1060  }
1061  }
1062 
1063  return topLeftPad;
1064 }
1065 
1066 
1067 unsigned FOOTPRINT::GetPadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
1068 {
1069  if( aIncludeNPTH )
1070  return m_pads.size();
1071 
1072  unsigned cnt = 0;
1073 
1074  for( PAD* pad : m_pads )
1075  {
1076  if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
1077  continue;
1078 
1079  cnt++;
1080  }
1081 
1082  return cnt;
1083 }
1084 
1085 
1086 unsigned FOOTPRINT::GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
1087 {
1088  std::set<wxString> usedNumbers;
1089 
1090  // Create a set of used pad numbers
1091  for( PAD* pad : m_pads )
1092  {
1093  // Skip pads not on copper layers (used to build complex
1094  // solder paste shapes for instance)
1095  if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none() )
1096  continue;
1097 
1098  // Skip pads with no name, because they are usually "mechanical"
1099  // pads, not "electrical" pads
1100  if( pad->GetNumber().IsEmpty() )
1101  continue;
1102 
1103  if( !aIncludeNPTH )
1104  {
1105  // skip NPTH
1106  if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
1107  continue;
1108  }
1109 
1110  usedNumbers.insert( pad->GetNumber() );
1111  }
1112 
1113  return usedNumbers.size();
1114 }
1115 
1116 
1118 {
1119  if( nullptr == a3DModel )
1120  return;
1121 
1122  if( !a3DModel->m_Filename.empty() )
1123  m_3D_Drawings.push_back( *a3DModel );
1124 }
1125 
1126 
1127 // see footprint.h
1128 SEARCH_RESULT FOOTPRINT::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
1129 {
1130  KICAD_T stype;
1132  const KICAD_T* p = scanTypes;
1133  bool done = false;
1134 
1135 #if 0 && defined(DEBUG)
1136  std::cout << GetClass().mb_str() << ' ';
1137 #endif
1138 
1139  while( !done )
1140  {
1141  stype = *p;
1142 
1143  switch( stype )
1144  {
1145  case PCB_FOOTPRINT_T:
1146  result = inspector( this, testData ); // inspect me
1147  ++p;
1148  break;
1149 
1150  case PCB_PAD_T:
1151  result = IterateForward<PAD*>( m_pads, inspector, testData, p );
1152  ++p;
1153  break;
1154 
1155  case PCB_FP_ZONE_T:
1156  result = IterateForward<FP_ZONE*>( m_fp_zones, inspector, testData, p );
1157  ++p;
1158  break;
1159 
1160  case PCB_FP_TEXT_T:
1161  result = inspector( m_reference, testData );
1162 
1163  if( result == SEARCH_RESULT::QUIT )
1164  break;
1165 
1166  result = inspector( m_value, testData );
1167 
1168  if( result == SEARCH_RESULT::QUIT )
1169  break;
1170 
1171  // Intentionally fall through since m_Drawings can hold PCB_FP_SHAPE_T also
1173 
1174  case PCB_FP_SHAPE_T:
1175  result = IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, p );
1176 
1177  // skip over any types handled in the above call.
1178  for( ; ; )
1179  {
1180  switch( stype = *++p )
1181  {
1182  case PCB_FP_TEXT_T:
1183  case PCB_FP_SHAPE_T:
1184  continue;
1185 
1186  default:
1187  ;
1188  }
1189 
1190  break;
1191  }
1192 
1193  break;
1194 
1195  case PCB_GROUP_T:
1196  result = IterateForward<PCB_GROUP*>( m_fp_groups, inspector, testData, p );
1197  ++p;
1198  break;
1199 
1200  default:
1201  done = true;
1202  break;
1203  }
1204 
1205  if( result == SEARCH_RESULT::QUIT )
1206  break;
1207  }
1208 
1209  return result;
1210 }
1211 
1212 
1213 wxString FOOTPRINT::GetSelectMenuText( EDA_UNITS aUnits ) const
1214 {
1215  wxString reference = GetReference();
1216 
1217  if( reference.IsEmpty() )
1218  reference = _( "<no reference designator>" );
1219 
1220  return wxString::Format( _( "Footprint %s" ), reference );
1221 }
1222 
1223 
1225 {
1226  return BITMAPS::module;
1227 }
1228 
1229 
1231 {
1232  return new FOOTPRINT( *this );
1233 }
1234 
1235 
1236 void FOOTPRINT::RunOnChildren( const std::function<void ( BOARD_ITEM*)>& aFunction ) const
1237 {
1238  try
1239  {
1240  for( PAD* pad : m_pads )
1241  aFunction( static_cast<BOARD_ITEM*>( pad ) );
1242 
1243  for( FP_ZONE* zone : m_fp_zones )
1244  aFunction( static_cast<FP_ZONE*>( zone ) );
1245 
1246  for( PCB_GROUP* group : m_fp_groups )
1247  aFunction( static_cast<PCB_GROUP*>( group ) );
1248 
1249  for( BOARD_ITEM* drawing : m_drawings )
1250  aFunction( static_cast<BOARD_ITEM*>( drawing ) );
1251 
1252  aFunction( static_cast<BOARD_ITEM*>( m_reference ) );
1253  aFunction( static_cast<BOARD_ITEM*>( m_value ) );
1254  }
1255  catch( std::bad_function_call& )
1256  {
1257  wxFAIL_MSG( "Error running FOOTPRINT::RunOnChildren" );
1258  }
1259 }
1260 
1261 
1262 void FOOTPRINT::GetAllDrawingLayers( int aLayers[], int& aCount, bool aIncludePads ) const
1263 {
1264  std::unordered_set<int> layers;
1265 
1266  for( BOARD_ITEM* item : m_drawings )
1267  layers.insert( static_cast<int>( item->GetLayer() ) );
1268 
1269  if( aIncludePads )
1270  {
1271  for( PAD* pad : m_pads )
1272  {
1273  int pad_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], pad_layers_count;
1274  pad->ViewGetLayers( pad_layers, pad_layers_count );
1275 
1276  for( int i = 0; i < pad_layers_count; i++ )
1277  layers.insert( pad_layers[i] );
1278  }
1279  }
1280 
1281  aCount = layers.size();
1282  int i = 0;
1283 
1284  for( int layer : layers )
1285  aLayers[i++] = layer;
1286 }
1287 
1288 
1289 void FOOTPRINT::ViewGetLayers( int aLayers[], int& aCount ) const
1290 {
1291  aCount = 2;
1292  aLayers[0] = LAYER_ANCHOR;
1293 
1294  switch( m_layer )
1295  {
1296  default:
1297  wxASSERT_MSG( false, "Illegal layer" ); // do you really have footprints placed on
1298  // other layers?
1300 
1301  case F_Cu:
1302  aLayers[1] = LAYER_MOD_FR;
1303  break;
1304 
1305  case B_Cu:
1306  aLayers[1] = LAYER_MOD_BK;
1307  break;
1308  }
1309 
1310  // If there are no pads, and only drawings on a silkscreen layer, then report the silkscreen
1311  // layer as well so that the component can be edited with the silkscreen layer
1312  bool f_silk = false, b_silk = false, non_silk = false;
1313 
1314  for( BOARD_ITEM* item : m_drawings )
1315  {
1316  if( item->GetLayer() == F_SilkS )
1317  f_silk = true;
1318  else if( item->GetLayer() == B_SilkS )
1319  b_silk = true;
1320  else
1321  non_silk = true;
1322  }
1323 
1324  if( ( f_silk || b_silk ) && !non_silk && m_pads.empty() )
1325  {
1326  if( f_silk )
1327  aLayers[ aCount++ ] = F_SilkS;
1328 
1329  if( b_silk )
1330  aLayers[ aCount++ ] = B_SilkS;
1331  }
1332 }
1333 
1334 
1335 double FOOTPRINT::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
1336 {
1337  int layer = ( m_layer == F_Cu ) ? LAYER_MOD_FR :
1339 
1340  // Currently this is only pertinent for the anchor layer; everything else is drawn from the
1341  // children.
1342  // The "good" value is experimentally chosen.
1343  #define MINIMAL_ZOOM_LEVEL_FOR_VISIBILITY 1.5
1344 
1345  if( aView->IsLayerVisible( layer ) )
1347 
1348  return std::numeric_limits<double>::max();
1349 }
1350 
1351 
1353 {
1354  EDA_RECT area = GetBoundingBox( true, true );
1355 
1356  // Add the Clearance shape size: (shape around the pads when the clearance is shown. Not
1357  // optimized, but the draw cost is small (perhaps smaller than optimization).
1358  const BOARD* board = GetBoard();
1359 
1360  if( board )
1361  {
1362  int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue();
1363  area.Inflate( biggest_clearance );
1364  }
1365 
1366  return area;
1367 }
1368 
1369 
1370 bool FOOTPRINT::IsLibNameValid( const wxString & aName )
1371 {
1372  const wxChar * invalids = StringLibNameInvalidChars( false );
1373 
1374  if( aName.find_first_of( invalids ) != std::string::npos )
1375  return false;
1376 
1377  return true;
1378 }
1379 
1380 
1381 const wxChar* FOOTPRINT::StringLibNameInvalidChars( bool aUserReadable )
1382 {
1383  // This list of characters is also duplicated in validators.cpp and
1384  // lib_id.cpp
1385  // TODO: Unify forbidden character lists
1386  static const wxChar invalidChars[] = wxT("%$<>\t\n\r\"\\/:");
1387  static const wxChar invalidCharsReadable[] = wxT("% $ < > 'tab' 'return' 'line feed' \\ \" / :");
1388 
1389  if( aUserReadable )
1390  return invalidCharsReadable;
1391  else
1392  return invalidChars;
1393 }
1394 
1395 
1396 void FOOTPRINT::Move( const wxPoint& aMoveVector )
1397 {
1398  wxPoint newpos = m_pos + aMoveVector;
1399  SetPosition( newpos );
1400 }
1401 
1402 
1403 void FOOTPRINT::Rotate( const wxPoint& aRotCentre, double aAngle )
1404 {
1405  double orientation = GetOrientation();
1406  double newOrientation = orientation + aAngle;
1407  wxPoint newpos = m_pos;
1408  RotatePoint( &newpos, aRotCentre, aAngle );
1409  SetPosition( newpos );
1410  SetOrientation( newOrientation );
1411 
1412  m_reference->KeepUpright( orientation, newOrientation );
1413  m_value->KeepUpright( orientation, newOrientation );
1414 
1415  for( BOARD_ITEM* item : m_drawings )
1416  {
1417  if( item->Type() == PCB_FP_TEXT_T )
1418  static_cast<FP_TEXT*>( item )->KeepUpright( orientation, newOrientation );
1419  }
1420 
1425 }
1426 
1427 
1428 void FOOTPRINT::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
1429 {
1430  // Move footprint to its final position:
1431  wxPoint finalPos = m_pos;
1432 
1433  // Now Flip the footprint.
1434  // Flipping a footprint is a specific transform: it is not mirrored like a text.
1435  // We have to change the side, and ensure the footprint rotation is modified according to the
1436  // transform, because this parameter is used in pick and place files, and when updating the
1437  // footprint from library.
1438  // When flipped around the X axis (Y coordinates changed) orientation is negated
1439  // When flipped around the Y axis (X coordinates changed) orientation is 180 - old orient.
1440  // Because it is specific to a footprint, we flip around the X axis, and after rotate 180 deg
1441 
1442  MIRROR( finalPos.y, aCentre.y );
1443 
1444  SetPosition( finalPos );
1445 
1446  // Flip layer
1447  SetLayer( FlipLayer( GetLayer() ) );
1448 
1449  // Reverse mirror orientation.
1450  m_orient = -m_orient;
1451 
1453 
1454  // Mirror pads to other side of board.
1455  for( PAD* pad : m_pads )
1456  pad->Flip( m_pos, false );
1457 
1458  // Mirror zones to other side of board.
1459  for( ZONE* zone : m_fp_zones )
1460  zone->Flip( m_pos, false );
1461 
1462  // Mirror reference and value.
1463  m_reference->Flip( m_pos, false );
1464  m_value->Flip( m_pos, false );
1465 
1466  // Reverse mirror footprint graphics and texts.
1467  for( BOARD_ITEM* item : m_drawings )
1468  {
1469  switch( item->Type() )
1470  {
1471  case PCB_FP_SHAPE_T:
1472  static_cast<FP_SHAPE*>( item )->Flip( m_pos, false );
1473  break;
1474 
1475  case PCB_FP_TEXT_T:
1476  static_cast<FP_TEXT*>( item )->Flip( m_pos, false );
1477  break;
1478 
1479  default:
1480  wxMessageBox( wxT( "FOOTPRINT::Flip() error: Unknown Draw Type" ) );
1481  break;
1482  }
1483  }
1484 
1485  // Now rotate 180 deg if required
1486  if( aFlipLeftRight )
1487  Rotate( aCentre, 1800.0 );
1488 
1492 
1493  m_cachedHull.Mirror( aFlipLeftRight, !aFlipLeftRight, m_pos );
1494 
1496 }
1497 
1498 
1499 void FOOTPRINT::SetPosition( const wxPoint& aPos )
1500 {
1501  wxPoint delta = aPos - m_pos;
1502 
1503  m_pos += delta;
1504 
1505  m_reference->EDA_TEXT::Offset( delta );
1506  m_value->EDA_TEXT::Offset( delta );
1507 
1508  for( PAD* pad : m_pads )
1509  pad->SetPosition( pad->GetPosition() + delta );
1510 
1511  for( ZONE* zone : m_fp_zones )
1512  zone->Move( delta );
1513 
1514  for( BOARD_ITEM* item : m_drawings )
1515  {
1516  switch( item->Type() )
1517  {
1518  case PCB_FP_SHAPE_T:
1519  {
1520  FP_SHAPE* shape = static_cast<FP_SHAPE*>( item );
1521  shape->SetDrawCoord();
1522  break;
1523  }
1524 
1525  case PCB_FP_TEXT_T:
1526  {
1527  FP_TEXT* text = static_cast<FP_TEXT*>( item );
1528  text->EDA_TEXT::Offset( delta );
1529  break;
1530  }
1531 
1532  default:
1533  wxMessageBox( wxT( "Draw type undefined." ) );
1534  break;
1535  }
1536  }
1537 
1541  m_cachedHull.Move( delta );
1542 }
1543 
1544 
1545 void FOOTPRINT::MoveAnchorPosition( const wxPoint& aMoveVector )
1546 {
1547  /* Move the reference point of the footprint
1548  * the footprints elements (pads, outlines, edges .. ) are moved
1549  * but:
1550  * - the footprint position is not modified.
1551  * - the relative (local) coordinates of these items are modified
1552  * - Draw coordinates are updated
1553  */
1554 
1555 
1556  // Update (move) the relative coordinates relative to the new anchor point.
1557  wxPoint moveVector = aMoveVector;
1558  RotatePoint( &moveVector, -GetOrientation() );
1559 
1560  // Update of the reference and value.
1561  m_reference->SetPos0( m_reference->GetPos0() + moveVector );
1563  m_value->SetPos0( m_value->GetPos0() + moveVector );
1564  m_value->SetDrawCoord();
1565 
1566  // Update the pad local coordinates.
1567  for( PAD* pad : m_pads )
1568  {
1569  pad->SetPos0( pad->GetPos0() + moveVector );
1570  pad->SetDrawCoord();
1571  }
1572 
1573  // Update the draw element coordinates.
1574  for( BOARD_ITEM* item : GraphicalItems() )
1575  {
1576  switch( item->Type() )
1577  {
1578  case PCB_FP_SHAPE_T:
1579  {
1580  FP_SHAPE* shape = static_cast<FP_SHAPE*>( item );
1581  shape->Move( moveVector );
1582  }
1583  break;
1584 
1585  case PCB_FP_TEXT_T:
1586  {
1587  FP_TEXT* text = static_cast<FP_TEXT*>( item );
1588  text->SetPos0( text->GetPos0() + moveVector );
1589  text->SetDrawCoord();
1590  }
1591  break;
1592 
1593  default:
1594  break;
1595  }
1596  }
1597 
1598  // Update the keepout zones
1599  for( ZONE* zone : Zones() )
1600  {
1601  zone->Move( moveVector );
1602  }
1603 
1604  // Update the 3D models
1605  for( FP_3DMODEL& model : Models() )
1606  {
1607  model.m_Offset.x += Iu2Millimeter( moveVector.x );
1608  model.m_Offset.y -= Iu2Millimeter( moveVector.y );
1609  }
1610 
1611  m_cachedBoundingBox.Move( moveVector );
1612  m_cachedVisibleBBox.Move( moveVector );
1613  m_cachedTextExcludedBBox.Move( moveVector );
1614  m_cachedHull.Move( moveVector );
1615 }
1616 
1617 
1618 void FOOTPRINT::SetOrientation( double aNewAngle )
1619 {
1620  double angleChange = aNewAngle - m_orient; // change in rotation
1621 
1622  NORMALIZE_ANGLE_180( aNewAngle );
1623 
1624  m_orient = aNewAngle;
1625 
1626  for( PAD* pad : m_pads )
1627  {
1628  pad->SetOrientation( pad->GetOrientation() + angleChange );
1629  pad->SetDrawCoord();
1630  }
1631 
1632  for( ZONE* zone : m_fp_zones )
1633  {
1634  zone->Rotate( GetPosition(), angleChange );
1635  }
1636 
1637  // Update of the reference and value.
1639  m_value->SetDrawCoord();
1640 
1641  // Displace contours and text of the footprint.
1642  for( BOARD_ITEM* item : m_drawings )
1643  {
1644  if( item->Type() == PCB_FP_SHAPE_T )
1645  {
1646  static_cast<FP_SHAPE*>( item )->SetDrawCoord();
1647  }
1648  else if( item->Type() == PCB_FP_TEXT_T )
1649  {
1650  static_cast<FP_TEXT*>( item )->SetDrawCoord();
1651  }
1652  }
1653 
1657 
1658  m_cachedHull.Rotate( -DECIDEG2RAD( angleChange ), GetPosition() );
1659 }
1660 
1661 
1663 {
1664  FOOTPRINT* dupe = (FOOTPRINT*) Clone();
1665  const_cast<KIID&>( dupe->m_Uuid ) = KIID();
1666 
1667  dupe->RunOnChildren( [&]( BOARD_ITEM* child )
1668  {
1669  const_cast<KIID&>( child->m_Uuid ) = KIID();
1670  });
1671 
1672  return static_cast<BOARD_ITEM*>( dupe );
1673 }
1674 
1675 
1676 BOARD_ITEM* FOOTPRINT::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToFootprint )
1677 {
1678  BOARD_ITEM* new_item = nullptr;
1679  FP_ZONE* new_zone = nullptr;
1680 
1681  switch( aItem->Type() )
1682  {
1683  case PCB_PAD_T:
1684  {
1685  PAD* new_pad = new PAD( *static_cast<const PAD*>( aItem ) );
1686  const_cast<KIID&>( new_pad->m_Uuid ) = KIID();
1687 
1688  if( aAddToFootprint )
1689  m_pads.push_back( new_pad );
1690 
1691  new_item = new_pad;
1692  break;
1693  }
1694 
1695  case PCB_FP_ZONE_T:
1696  {
1697  new_zone = new FP_ZONE( *static_cast<const FP_ZONE*>( aItem ) );
1698  const_cast<KIID&>( new_zone->m_Uuid ) = KIID();
1699 
1700  if( aAddToFootprint )
1701  m_fp_zones.push_back( new_zone );
1702 
1703  new_item = new_zone;
1704  break;
1705  }
1706 
1707  case PCB_FP_TEXT_T:
1708  {
1709  FP_TEXT* new_text = new FP_TEXT( *static_cast<const FP_TEXT*>( aItem ) );
1710  const_cast<KIID&>( new_text->m_Uuid ) = KIID();
1711 
1712  if( new_text->GetType() == FP_TEXT::TEXT_is_REFERENCE )
1713  {
1714  new_text->SetText( wxT( "${REFERENCE}" ) );
1715  new_text->SetType( FP_TEXT::TEXT_is_DIVERS );
1716  }
1717  else if( new_text->GetType() == FP_TEXT::TEXT_is_VALUE )
1718  {
1719  new_text->SetText( wxT( "${VALUE}" ) );
1720  new_text->SetType( FP_TEXT::TEXT_is_DIVERS );
1721  }
1722 
1723  if( aAddToFootprint )
1724  Add( new_text );
1725 
1726  new_item = new_text;
1727 
1728  break;
1729  }
1730 
1731  case PCB_FP_SHAPE_T:
1732  {
1733  FP_SHAPE* new_shape = new FP_SHAPE( *static_cast<const FP_SHAPE*>( aItem ) );
1734  const_cast<KIID&>( new_shape->m_Uuid ) = KIID();
1735 
1736  if( aAddToFootprint )
1737  Add( new_shape );
1738 
1739  new_item = new_shape;
1740  break;
1741  }
1742 
1743  case PCB_GROUP_T:
1744  new_item = static_cast<const PCB_GROUP*>( aItem )->DeepDuplicate();
1745  break;
1746 
1747  case PCB_FOOTPRINT_T:
1748  // Ignore the footprint itself
1749  break;
1750 
1751  default:
1752  // Un-handled item for duplication
1753  wxFAIL_MSG( "Duplication not supported for items of class " + aItem->GetClass() );
1754  break;
1755  }
1756 
1757  return new_item;
1758 }
1759 
1760 
1761 wxString FOOTPRINT::GetNextPadNumber( const wxString& aLastPadNumber ) const
1762 {
1763  std::set<wxString> usedNumbers;
1764 
1765  // Create a set of used pad numbers
1766  for( PAD* pad : m_pads )
1767  usedNumbers.insert( pad->GetNumber() );
1768 
1769  // Pad numbers aren't technically reference designators, but the formatting is close enough
1770  // for these to give us what we need.
1771  wxString prefix = UTIL::GetRefDesPrefix( aLastPadNumber );
1772  int num = GetTrailingInt( aLastPadNumber );
1773 
1774  while( usedNumbers.count( wxString::Format( "%s%d", prefix, num ) ) )
1775  num++;
1776 
1777  return wxString::Format( "%s%d", prefix, num );
1778 }
1779 
1780 
1782 {
1783  const wxString& refdes = GetReference();
1784 
1785  SetReference( wxString::Format( wxT( "%s%i" ),
1786  UTIL::GetRefDesPrefix( refdes ),
1787  GetTrailingInt( refdes ) + aDelta ) );
1788 }
1789 
1790 
1791 // Calculate the area of a PolySet, polygons with hole are allowed.
1792 static double polygonArea( SHAPE_POLY_SET& aPolySet )
1793 {
1794  // Ensure all outlines are closed, before calculating the SHAPE_POLY_SET area
1795  for( int ii = 0; ii < aPolySet.OutlineCount(); ii++ )
1796  {
1797  SHAPE_LINE_CHAIN& outline = aPolySet.Outline( ii );
1798  outline.SetClosed( true );
1799 
1800  for( int jj = 0; jj < aPolySet.HoleCount( ii ); jj++ )
1801  aPolySet.Hole( ii, jj ).SetClosed( true );
1802  }
1803 
1804  return aPolySet.Area();
1805 }
1806 
1807 
1808 double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLECTOR& aCollector )
1809 {
1810  int textMargin = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
1811  SHAPE_POLY_SET poly;
1812 
1813  if( aItem->Type() == PCB_MARKER_T )
1814  {
1815  const PCB_MARKER* marker = static_cast<const PCB_MARKER*>( aItem );
1816  SHAPE_LINE_CHAIN markerShape;
1817 
1818  marker->ShapeToPolygon( markerShape );
1819  return markerShape.Area();
1820  }
1821  else if( aItem->Type() == PCB_GROUP_T )
1822  {
1823  double combinedArea = 0.0;
1824 
1825  for( BOARD_ITEM* member : static_cast<const PCB_GROUP*>( aItem )->GetItems() )
1826  combinedArea += GetCoverageArea( member, aCollector );
1827 
1828  return combinedArea;
1829  }
1830  if( aItem->Type() == PCB_FOOTPRINT_T )
1831  {
1832  const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
1833 
1834  poly = footprint->GetBoundingHull();
1835  }
1836  else if( aItem->Type() == PCB_FP_TEXT_T )
1837  {
1838  const FP_TEXT* text = static_cast<const FP_TEXT*>( aItem );
1839 
1840  text->TransformTextShapeWithClearanceToPolygon( poly, UNDEFINED_LAYER, textMargin,
1841  ARC_LOW_DEF, ERROR_OUTSIDE );
1842  }
1843  else if( aItem->Type() == PCB_SHAPE_T )
1844  {
1845  // Approximate "linear" shapes with just their width squared, as we don't want to consider
1846  // a linear shape as being much bigger than another for purposes of selection filtering
1847  // just because it happens to be really long.
1848 
1849  const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
1850 
1851  switch( shape->GetShape() )
1852  {
1853  case SHAPE_T::SEGMENT:
1854  case SHAPE_T::ARC:
1855  case SHAPE_T::BEZIER:
1856  return shape->GetWidth() * shape->GetWidth();
1857 
1858  case SHAPE_T::RECT:
1859  case SHAPE_T::CIRCLE:
1860  case SHAPE_T::POLY:
1861  {
1862  if( !shape->IsFilled() )
1863  return shape->GetWidth() * shape->GetWidth();
1864 
1866  }
1867 
1868  default:
1870  ARC_LOW_DEF, ERROR_OUTSIDE );
1871  }
1872  }
1873  else if( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_ARC_T )
1874  {
1875  double width = static_cast<const PCB_TRACK*>( aItem )->GetWidth();
1876  return width * width;
1877  }
1878  else
1879  {
1881  ARC_LOW_DEF, ERROR_OUTSIDE );
1882  }
1883 
1884  return polygonArea( poly );
1885 }
1886 
1887 
1888 double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
1889 {
1890  int textMargin = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() );
1891 
1892  SHAPE_POLY_SET footprintRegion( GetBoundingHull() );
1893  SHAPE_POLY_SET coveredRegion;
1894 
1895  TransformPadsWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 0, ARC_LOW_DEF,
1896  ERROR_OUTSIDE );
1897 
1898  TransformFPShapesWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, textMargin,
1899  ARC_LOW_DEF, ERROR_OUTSIDE,
1900  true, /* include text */
1901  false /* include shapes */ );
1902 
1903  for( int i = 0; i < aCollector.GetCount(); ++i )
1904  {
1905  const BOARD_ITEM* item = aCollector[i];
1906 
1907  switch( item->Type() )
1908  {
1909  case PCB_FP_TEXT_T:
1910  case PCB_FP_SHAPE_T:
1911  if( item->GetParent() != this )
1912  {
1913  item->TransformShapeWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 0,
1914  ARC_LOW_DEF, ERROR_OUTSIDE );
1915  }
1916  break;
1917 
1918  case PCB_TEXT_T:
1919  case PCB_SHAPE_T:
1920  case PCB_TRACE_T:
1921  case PCB_ARC_T:
1922  case PCB_VIA_T:
1923  item->TransformShapeWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, 0,
1924  ARC_LOW_DEF, ERROR_OUTSIDE );
1925  break;
1926 
1927  case PCB_FOOTPRINT_T:
1928  if( item != this )
1929  {
1930  const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( item );
1931  coveredRegion.AddOutline( footprint->GetBoundingHull().Outline( 0 ) );
1932  }
1933  break;
1934 
1935  default:
1936  break;
1937  }
1938  }
1939 
1940  double footprintRegionArea = polygonArea( footprintRegion );
1941  double uncoveredRegionArea = footprintRegionArea - polygonArea( coveredRegion );
1942  double coveredArea = footprintRegionArea - uncoveredRegionArea;
1943  double ratio = ( coveredArea / footprintRegionArea );
1944 
1945  // Test for negative ratio (should not occur).
1946  // better to be conservative (this will result in the disambiguate dialog)
1947  if( ratio < 0.0 )
1948  return 1.0;
1949 
1950  return std::min( ratio, 1.0 );
1951 }
1952 
1953 
1954 std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
1955 {
1956  std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
1957 
1958  // There are several possible interpretations here:
1959  // 1) the bounding box (without or without invisible items)
1960  // 2) just the pads and "edges" (ie: non-text graphic items)
1961  // 3) the courtyard
1962 
1963  // We'll go with (2) for now....
1964 
1965  for( PAD* pad : Pads() )
1966  shape->AddShape( pad->GetEffectiveShape( aLayer )->Clone() );
1967 
1968  for( BOARD_ITEM* item : GraphicalItems() )
1969  {
1970  if( item->Type() == PCB_FP_SHAPE_T )
1971  shape->AddShape( item->GetEffectiveShape( aLayer )->Clone() );
1972  }
1973 
1974  return shape;
1975 }
1976 
1977 
1979 {
1983 
1984  // Build the courtyard area from graphic items on the courtyard.
1985  // Only PCB_FP_SHAPE_T have meaning, graphic texts are ignored.
1986  // Collect items:
1987  std::vector<PCB_SHAPE*> list_front;
1988  std::vector<PCB_SHAPE*> list_back;
1989 
1990  for( BOARD_ITEM* item : GraphicalItems() )
1991  {
1992  if( item->GetLayer() == B_CrtYd && item->Type() == PCB_FP_SHAPE_T )
1993  list_back.push_back( static_cast<PCB_SHAPE*>( item ) );
1994 
1995  if( item->GetLayer() == F_CrtYd && item->Type() == PCB_FP_SHAPE_T )
1996  list_front.push_back( static_cast<PCB_SHAPE*>( item ) );
1997  }
1998 
1999  if( !list_front.size() && !list_back.size() )
2000  return;
2001 
2002  int errorMax = Millimeter2iu( 0.02 ); // max error for polygonization
2003  int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
2004 
2005  if( ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, errorMax, chainingEpsilon,
2006  aErrorHandler ) )
2007  {
2008  // Touching courtyards, or courtyards -at- the clearance distance are legal.
2010 
2012  }
2013  else
2014  {
2016  }
2017 
2018  if( ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, errorMax, chainingEpsilon,
2019  aErrorHandler ) )
2020  {
2021  // Touching courtyards, or courtyards -at- the clearance distance are legal.
2023 
2025  }
2026  else
2027  {
2029  }
2030 }
2031 
2032 
2034 {
2035  wxASSERT( aImage->Type() == PCB_FOOTPRINT_T );
2036 
2037  std::swap( *((FOOTPRINT*) this), *((FOOTPRINT*) aImage) );
2038 }
2039 
2040 
2042 {
2043  for( PAD* pad : Pads() )
2044  {
2045  if( pad->GetAttribute() != PAD_ATTRIB::SMD )
2046  return true;
2047  }
2048 
2049  return false;
2050 }
2051 
2052 
2054  const BOARD_ITEM* aSecond ) const
2055 {
2056  if( aFirst->Type() != aSecond->Type() )
2057  return aFirst->Type() < aSecond->Type();
2058 
2059  if( aFirst->GetLayer() != aSecond->GetLayer() )
2060  return aFirst->GetLayer() < aSecond->GetLayer();
2061 
2062  if( aFirst->Type() == PCB_FP_SHAPE_T )
2063  {
2064  const FP_SHAPE* dwgA = static_cast<const FP_SHAPE*>( aFirst );
2065  const FP_SHAPE* dwgB = static_cast<const FP_SHAPE*>( aSecond );
2066 
2067  if( dwgA->GetShape() != dwgB->GetShape() )
2068  return dwgA->GetShape() < dwgB->GetShape();
2069  }
2070 
2071  if( aFirst->m_Uuid != aSecond->m_Uuid ) // shopuld be always the case foer valid boards
2072  return aFirst->m_Uuid < aSecond->m_Uuid;
2073 
2074  return aFirst < aSecond;
2075 }
2076 
2077 
2078 bool FOOTPRINT::cmp_pads::operator()( const PAD* aFirst, const PAD* aSecond ) const
2079 {
2080  if( aFirst->GetNumber() != aSecond->GetNumber() )
2081  return StrNumCmp( aFirst->GetNumber(), aSecond->GetNumber() ) < 0;
2082 
2083  if( aFirst->m_Uuid != aSecond->m_Uuid ) // shopuld be always the case foer valid boards
2084  return aFirst->m_Uuid < aSecond->m_Uuid;
2085 
2086  return aFirst < aSecond;
2087 }
2088 
2089 
2090 static struct FOOTPRINT_DESC
2091 {
2093  {
2095 
2096  if( layerEnum.Choices().GetCount() == 0 )
2097  {
2098  layerEnum.Undefined( UNDEFINED_LAYER );
2099 
2100  for( LSEQ seq = LSET::AllLayersMask().Seq(); seq; ++seq )
2101  layerEnum.Map( *seq, LSET::Name( *seq ) );
2102  }
2103 
2104  wxPGChoices fpLayers; // footprints might be placed only on F.Cu & B.Cu
2105  fpLayers.Add( LSET::Name( F_Cu ), F_Cu );
2106  fpLayers.Add( LSET::Name( B_Cu ), B_Cu );
2107 
2114 
2115  auto layer = new PROPERTY_ENUM<FOOTPRINT, PCB_LAYER_ID, BOARD_ITEM>( _HKI( "Layer" ),
2117  layer->SetChoices( fpLayers );
2118  propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _HKI( "Layer" ), layer );
2119 
2120  propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Reference" ),
2122  propMgr.AddProperty( new PROPERTY<FOOTPRINT, wxString>( _HKI( "Value" ),
2124  propMgr.AddProperty( new PROPERTY<FOOTPRINT, double>( _HKI( "Orientation" ),
2127  propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Clearance Override" ),
2130  propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Solderpaste Margin Override" ),
2133  propMgr.AddProperty( new PROPERTY<FOOTPRINT,
2134  double>( _HKI( "Solderpaste Margin Ratio Override" ),
2137  propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Thermal Relief Width" ),
2141  propMgr.AddProperty( new PROPERTY<FOOTPRINT, int>( _HKI( "Thermal Relief Gap" ),
2145  // TODO zone connection, FPID?
2146  }
2147 } _FOOTPRINT_DESC;
void SetReference(const wxString &aReference)
Definition: footprint.h:439
void BuildPolyCourtyards(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:1978
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
Display value expressed in degrees.
Definition: property.h:54
PCB_GROUP * GetParentGroup() const
Definition: board_item.h:91
int m_localSolderPasteMargin
Definition: footprint.h:729
BOARD_ITEM * DuplicateItem(const BOARD_ITEM *aItem, bool aAddToFootprint=false)
Duplicate a given item within the footprint, optionally adding it to the board.
Definition: footprint.cpp:1676
static double GetCoverageArea(const BOARD_ITEM *aItem, const GENERAL_COLLECTOR &aCollector)
Return the initial comments block or NULL if none, without transfer of ownership.
Definition: footprint.cpp:1808
bool IsLocked() const override
Definition: footprint.h:286
bool AddItem(BOARD_ITEM *aItem)
Add item to group.
Definition: pcb_group.cpp:38
double GetArea(int aPadding=0) const
Definition: footprint.cpp:643
void ClearAllNets()
Clear (i.e.
Definition: footprint.cpp:504
double ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition: footprint.cpp:1335
Arcs (with rounded ends)
bool IsFilled() const
Definition: pcb_shape.h:75
Bezier Curve.
void KeepUpright(double aOldOrientation, double aNewOrientation)
Called when rotating the parent footprint.
Definition: fp_text.cpp:105
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:65
EDA_RECT m_cachedVisibleBBox
Definition: footprint.h:717
#define TYPE_HASH(x)
Definition: property.h:59
void Move(const wxPoint &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: eda_rect.cpp:51
SHAPE_POLY_SET GetBoundingHull() const
Return a bounding polygon for the shapes and pads in the footprint.
Definition: footprint.cpp:787
int OutlineCount() const
Return the number of vertices in a given outline/hole.
KIID niluuid(0)
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
void Merge(const EDA_RECT &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: eda_rect.cpp:432
bool FixUuids()
Old footprints do not alway have a valid UUID (some can be set to null uuid) However null UUIDs,...
Definition: footprint.cpp:227
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: footprint.cpp:1213
#define MALFORMED_B_COURTYARD
std::list< FP_3DMODEL > & Models()
Definition: footprint.h:182
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Definition: footprint.cpp:864
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
A special IsOnLayer for footprints: return true if the footprint contains only items on the given lay...
Definition: footprint.cpp:930
polygon (not yet used for tracks, but could be in microwave apps)
const wxString & GetValue() const
Definition: footprint.h:452
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
Return the number of pads.
Definition: footprint.cpp:1067
ZONE_CONNECTION m_zoneConnection
Definition: footprint.h:724
double m_localSolderPasteMarginRatio
Definition: footprint.h:730
SHAPE_POLY_SET m_poly_courtyard_back
Definition: footprint.h:747
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.
virtual void SetPosition(const wxPoint &aPos)
Definition: eda_item.h:253
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
int GetTimeStamp() const
Definition: board.h:214
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
SHAPE_T GetShape() const
Definition: pcb_shape.h:110
show footprints values (when texts are visible)
Definition: layer_ids.h:205
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
virtual double OnePixelInIU() const =0
ENUM_MAP & Undefined(T aValue)
Definition: property.h:523
#define FP_PADS_are_LOCKED
Definition: footprint.h:283
double m_orient
Definition: footprint.h:697
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
Definition: footprint.cpp:477
#define MALFORMED_F_COURTYARD
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:521
int GetWidth() const
Definition: pcb_shape.h:97
Smd pad, appears on the solder paste layer (default)
timestamp_t m_lastEditTime
Definition: footprint.h:735
Collection of utility functions for component reference designators (refdes)
int GetWidth() const
Definition: eda_rect.h:109
usual segment : line with rounded ends
void Remove(BOARD_ITEM *aItem, REMOVE_MODE aMode=REMOVE_MODE::NORMAL) override
Removes an item from the container.
Definition: footprint.cpp:566
static ENUM_MAP< T > & Instance()
Definition: property.h:510
double GetOrientation() const
Definition: footprint.h:190
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:153
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:196
bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
double CoverageRatio(const GENERAL_COLLECTOR &aCollector) const
Calculate the ratio of total area of the footprint pads and graphical items to the area of the footpr...
Definition: footprint.cpp:1888
int GetTrailingInt(const wxString &aStr)
Gets the trailing int, if any, from a string.
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
void SetDrawCoord()
Set relative coordinates.
Definition: fp_text.cpp:190
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:121
double Area()
Count the number of arc shapes present.
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: footprint.h:224
functions to convert a shape built with DRAWSEGMENTS to a polygon.
static struct FOOTPRINT_DESC _FOOTPRINT_DESC
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
void SetOrientationDegrees(double aOrientation)
Definition: footprint.h:189
FP_TEXT * m_reference
Definition: footprint.h:699
show footprints on back
Definition: layer_ids.h:204
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int m_visibleBBoxCacheTimeStamp
Definition: footprint.h:718
double Area(bool aAbsolute=true) const
Return the area of this chain.
INCLUDE_NPTH_T
Definition: footprint.h:55
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:398
wxPGChoices & Choices()
Definition: property.h:559
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
void SetThermalGap(int aGap)
Definition: footprint.h:232
The base class for create windows for drawing purpose.
void SetType(TEXT_TYPE aType)
Definition: fp_text.h:140
std::unordered_set< BOARD_ITEM * > & GetItems()
Definition: pcb_group.h:68
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:589
#define REGISTER_TYPE(x)
Definition: property_mgr.h:248
bool Contains(const wxPoint &aPoint) const
Definition: eda_rect.cpp:57
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: footprint.cpp:1224
const INSPECTOR_FUNC & INSPECTOR
Definition: eda_item.h:94
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
bool operator()(const PAD *aFirst, const PAD *aSecond) const
Definition: footprint.cpp:2078
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:726
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
int m_rot90Cost
Definition: footprint.h:738
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both)
PADS & Pads()
Definition: footprint.h:168
This file contains miscellaneous commonly used macros and functions.
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: footprint.cpp:2033
void Add3DModel(FP_3DMODEL *a3DModel)
Add a3DModel definition to the end of the 3D model list.
Definition: footprint.cpp:1117
void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:40
const char * c_str() const
Definition: utf8.h:102
FP_TEXT * m_value
Definition: footprint.h:700
PAD * GetTopLeftPad()
Definition: footprint.cpp:1048
void SetThermalWidth(int aWidth)
Definition: footprint.h:229
int m_arflag
Definition: footprint.h:736
KIID m_link
Definition: footprint.h:737
int m_localSolderMaskMargin
Definition: footprint.h:728
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:72
EDA_RECT m_cachedBoundingBox
Definition: footprint.h:715
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
FP_ZONES & Zones()
Definition: footprint.h:174
Definition: kiid.h:44
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int m_fpStatus
Definition: footprint.h:703
like PAD_PTH, but not plated
Display value expressed in distance units (mm/inch)
Definition: property.h:53
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: footprint.cpp:1352
const COLLECTORS_GUIDE * GetGuide() const
Definition: collectors.h:339
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
FP_ZONES m_fp_zones
Definition: footprint.h:694
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
void Move(const VECTOR2I &aVector) override
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip entity during footprint flip.
Definition: fp_text.cpp:137
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: footprint.cpp:1289
SHAPE_POLY_SET m_poly_courtyard_front
Definition: footprint.h:746
void IncrementReference(int aDelta)
Bump the current reference by aDelta.
Definition: footprint.cpp:1781
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:82
TEXT_TYPE GetType() const
Definition: fp_text.h:141
Represent a set of closed polygons.
SHAPE_POLY_SET m_cachedHull
Definition: footprint.h:721
SHAPE_LINE_CHAIN & Outline(int aIndex)
virtual bool IsVisible() const
Definition: eda_text.h:186
void SetEnd(int x, int y)
Definition: eda_rect.h:182
PAD * GetPad(const wxPoint &aPosition, LSET aLayerMask=LSET::AllLayersMask())
Get a pad at aPosition on aLayerMask in the footprint.
Definition: footprint.cpp:1032
#define MINIMAL_ZOOM_LEVEL_FOR_VISIBILITY
void SetOrientation(double aNewAngle)
Definition: footprint.cpp:1618
void Move(const wxPoint &aMoveVector) override
Move this object.
Definition: footprint.cpp:1396
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: footprint.cpp:1428
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
show footprints on front
Definition: layer_ids.h:203
const wxString & GetNumber() const
Definition: pad.h:129
PAD * FindPadByNumber(const wxString &aPadNumber, PAD *aSearchAfterMe=nullptr) const
Return a PAD with a matching number.
Definition: footprint.cpp:1012
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
May be re-implemented for each derived class in order to handle all the types given by its member dat...
Definition: footprint.cpp:1128
int GetLocalClearance() const
Definition: footprint.h:209
void SetLocalClearance(int aClearance)
Definition: footprint.h:210
int m_thermalGap
Definition: footprint.h:726
const wxString & GetReference() const
Definition: footprint.h:430
#define STRUCT_DELETED
flag indication structures to be erased
#define _(s)
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: eda_item.h:154
BOARD_ITEM * Duplicate() const override
Create a copy of this BOARD_ITEM.
Definition: footprint.cpp:1662
DRAWINGS & GraphicalItems()
Definition: footprint.h:171
void MoveAnchorPosition(const wxPoint &aMoveVector)
Move the reference point of the footprint.
Definition: footprint.cpp:1545
static LSET AllLayersMask()
Definition: lset.cpp:787
bool RemoveItem(BOARD_ITEM *aItem)
Remove item from group.
Definition: pcb_group.cpp:50
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
wxString GetNextPadNumber(const wxString &aLastPadName) const
Return the next available pad number in the footprint.
Definition: footprint.cpp:1761
wxPoint m_pos
Definition: footprint.h:698
void SetValue(const wxString &aValue)
Definition: footprint.h:460
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate this object.
Definition: footprint.cpp:1403
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
Definition: fp_shape.cpp:82
int NewOutline()
Creates a new hole in a given outline.
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
Acute angles are chamfered.
bool ConvertOutlineToPolygon(std::vector< PCB_SHAPE * > &aSegList, SHAPE_POLY_SET &aPolygons, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler)
Function ConvertOutlineToPolygon Build a polygon (with holes) from a PCB_SHAPE list,...
void TransformPadsWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aSkipNPTHPadsWihNoCopper=false, bool aSkipPlatedPads=false, bool aSkipNonPlatedPads=false) const
Generate pads shapes on layer aLayer as polygons and adds these polygons to aCornerBuffer.
int GetThermalWidth() const
Definition: footprint.h:230
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition: eda_item.cpp:180
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:463
int GetHeight() const
Definition: eda_rect.h:110
UTF8 Format() const
Definition: lib_id.cpp:116
void SetPos0(const wxPoint &aPos)
Definition: fp_text.h:165
int m_boundingBoxCacheTimeStamp
Definition: footprint.h:716
static const int ORPHANED
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition: netinfo.h:369
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:155
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
void Inflate(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
KIID_PATH m_path
Definition: footprint.h:734
const KIID m_Uuid
Definition: eda_item.h:475
bool IsElementVisible(GAL_LAYER_ID aLayer) const
Test whether a given element category is visible.
Definition: board.cpp:532
Some functions to handle hotkeys in KiCad.
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
wxString m_Filename
The 3D shape filename in 3D library.
Definition: footprint.h:97
void ShapeToPolygon(SHAPE_LINE_CHAIN &aPolygon, int aScale=-1) const
Return the shape polygon in internal units in a SHAPE_LINE_CHAIN the coordinates are relatives to the...
const wxPoint & GetPos0() const
Definition: fp_text.h:166
EDA_UNITS
Definition: eda_units.h:38
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
Definition: footprint.cpp:2053
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars for this footprint.
Definition: footprint.cpp:469
bool IsFlipped() const
Definition: footprint.h:270
FP_GROUPS & Groups()
Definition: footprint.h:177
show footprints references (when texts are visible)
Definition: layer_ids.h:206
double GetOrientationDegrees() const
Definition: footprint.h:191
int m_thermalWidth
Definition: footprint.h:725
wxString m_keywords
Definition: footprint.h:733
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
Definition: board.cpp:472
const EDA_RECT GetBoundingBox() const override
Set absolute coordinates.
Definition: fp_text.cpp:227
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
FOOTPRINT(BOARD *parent)
Definition: footprint.cpp:51
int m_localClearance
Definition: footprint.h:727
virtual wxString GetClass() const =0
Return the class name.
bool IsType(FRAME_T aType) const
int m_rot180Cost
Definition: footprint.h:739
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:32
int m_textExcludedBBoxCacheTimeStamp
Definition: footprint.h:720
wxPoint GetPosition() const override
Definition: pad.h:178
wxString GetClass() const override
Return the class name.
Definition: footprint.h:563
void TransformFPShapesWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIncludeText=true, bool aIncludeShapes=true) const
Generate shapes of graphic items (outlines) on layer aLayer as polygons and adds these polygons to aC...
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
Represent a polyline (an zero-thickness chain of connected line segments).
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
LIB_ID m_fpid
Definition: footprint.h:701
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
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:676
Definition: layer_ids.h:70
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
void AddProperty(PROPERTY_BASE *aProperty)
Register a property.
class ZONE, managed by a footprint
Definition: typeinfo.h:94
Handle the component boundary box.
Definition: eda_rect.h:42
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
FOOTPRINT & operator=(const FOOTPRINT &aOther)
Definition: footprint.cpp:365
unsigned GetUniquePadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
Return the number of unique non-blank pads.
Definition: footprint.cpp:1086
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
EDA_RECT m_cachedTextExcludedBBox
Definition: footprint.h:719
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const wxPoint &pt)> OUTLINE_ERROR_HANDLER
wxPoint GetPosition() const override
Definition: footprint.h:186
double GetLocalSolderPasteMarginRatio() const
Definition: footprint.h:223
bool Intersects(const EDA_RECT &aRect) const
Test for a common area between rectangles.
Definition: eda_rect.cpp:150
PCB_LAYER_ID m_layer
Definition: board_item.h:353
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
DRAWINGS m_drawings
Definition: footprint.h:692
void ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew)
Replace an existing property for a specific type.
void GetAllDrawingLayers(int aLayers[], int &aCount, bool aIncludePads=true) const
Return a set of all layers that this footprint has drawings on similar to ViewGetLayers().
Definition: footprint.cpp:1262
constexpr int delta
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:50
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:62
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction) const
Invoke a function on all BOARD_ITEMs that belong to the footprint (pads, drawings,...
Definition: footprint.cpp:1236
void CacheTriangulation(bool aPartition=true)
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
void Move(const wxPoint &aMoveVector) override
Move an edge of the footprint.
Definition: fp_shape.cpp:289
virtual void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the item shape to a closed polygon.
Definition: board_item.cpp:156
std::map< wxString, wxString > m_properties
Definition: footprint.h:742
static bool IsLibNameValid(const wxString &aName)
Test for validity of a name of a footprint to be used in a footprint library ( no spaces,...
Definition: footprint.cpp:1370
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Test if aPosition is contained within or on the bounding box of an item.
Definition: footprint.cpp:953
int StrNumCmp(const wxString &aString1, const wxString &aString2, bool aIgnoreCase)
Compare two strings with alphanumerical content.
Abstract interface for BOARD_ITEMs capable of storing other items inside.
int GetLocalSolderPasteMargin() const
Definition: footprint.h:220
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Removes an item from the container.
Definition: footprint.cpp:513
wxArrayString * m_initial_comments
Definition: footprint.h:743
#define FP_is_PLACED
In autoplace: footprint automatically placed.
Definition: footprint.h:281
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition: property.h:516
segment with non rounded ends
Definition: pad.h:57
void SetPosition(const wxPoint &aPos) override
Definition: footprint.cpp:1499
void ClearEditFlags()
Definition: eda_item.h:172
SEARCH_RESULT
Definition: eda_item.h:41
FP_GROUPS m_fp_groups
Definition: footprint.h:695
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: footprint.cpp:1230
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:166
#define MALFORMED_COURTYARDS
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:414
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:87
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
static constexpr int Millimeter2iu(double mm)
#define _HKI(x)
bool HasThroughHolePads() const
Definition: footprint.cpp:2041
wxString m_doc
Definition: footprint.h:732
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
bool HitTestAccurate(const wxPoint &aPosition, int aAccuracy=0) const
Test if a point is inside the bounding polygon of the footprint.
Definition: footprint.cpp:960
int GetThermalGap() const
Definition: footprint.h:233
std::list< FP_3DMODEL > m_3D_Drawings
Definition: footprint.h:741
A specialization of ZONE for use in footprints.
Definition: zone.h:946
PADS m_pads
Definition: footprint.h:693
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
Test for validity of the name in a library of the footprint ( no spaces, dir separators ....
Definition: footprint.cpp:1381
int m_hullCacheTimeStamp
Definition: footprint.h:722
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
int m_attributes
Definition: footprint.h:702
EDA_RECT GetFpPadsLocalBbox() const
Return the bounding box containing pads when the footprint is on the front side, orientation 0,...
Definition: footprint.cpp:653
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:405
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: footprint.cpp:1954
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...
static double polygonArea(SHAPE_POLY_SET &aPolySet)
Definition: footprint.cpp:1792
void BuildConvexHull(std::vector< wxPoint > &aResult, const std::vector< wxPoint > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
Definition: convex_hull.cpp:87
void SetLocalSolderPasteMargin(int aMargin)
Definition: footprint.h:221