KiCad PCB EDA Suite
class_module.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-2020 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 <fctsys.h>
28 #include <gr_basic.h>
29 #include <confirm.h>
30 #include <refdes_utils.h>
31 #include <bitmaps.h>
32 #include <unordered_set>
33 #include <pcb_edit_frame.h>
34 #include <class_board.h>
35 #include <class_edge_mod.h>
36 #include <class_module.h>
37 #include <view/view.h>
38 
39 MODULE::MODULE( BOARD* parent ) :
41  m_initial_comments( 0 )
42 {
44  m_Layer = F_Cu;
45  m_Orient = 0;
47  m_arflag = 0;
48  m_CntRot90 = m_CntRot180 = 0;
49  m_Link = 0;
50  m_LastEditTime = 0;
51  m_LocalClearance = 0;
55  m_ZoneConnection = ZONE_CONNECTION::INHERITED; // Use zone setting by default
56  m_ThermalWidth = 0; // Use zone setting by default
57  m_ThermalGap = 0; // Use zone setting by default
58 
59  // These are special and mandatory text fields
62 
63  m_3D_Drawings.clear();
64 }
65 
66 
67 MODULE::MODULE( const MODULE& aModule ) :
68  BOARD_ITEM_CONTAINER( aModule )
69 {
70  m_Pos = aModule.m_Pos;
71  m_fpid = aModule.m_fpid;
72  m_Attributs = aModule.m_Attributs;
74  m_Orient = aModule.m_Orient;
75  m_BoundaryBox = aModule.m_BoundaryBox;
76  m_CntRot90 = aModule.m_CntRot90;
77  m_CntRot180 = aModule.m_CntRot180;
79  m_Link = aModule.m_Link;
80  m_Path = aModule.m_Path;
81 
88  m_ThermalGap = aModule.m_ThermalGap;
89 
90  // Copy reference and value.
91  m_Reference = new TEXTE_MODULE( *aModule.m_Reference );
92  m_Reference->SetParent( this );
93  m_Value = new TEXTE_MODULE( *aModule.m_Value );
94  m_Value->SetParent( this );
95 
96  // Copy auxiliary data: Pads
97  for( D_PAD* pad : aModule.Pads() )
98  Add( new D_PAD( *pad ) );
99 
100  // Copy auxiliary data: Zones
101  for( MODULE_ZONE_CONTAINER* item : aModule.Zones() )
102  {
103  Add( static_cast<MODULE_ZONE_CONTAINER*>( item->Clone() ) );
104 
105  // Ensure the net info is OK and especially uses the net info list
106  // living in the current board
107  // Needed when copying a fp from fp editor that has its own board
108  // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
109  item->SetNetCode( -1 );
110  }
111 
112  // Copy auxiliary data: Drawings
113  for( BOARD_ITEM* item : aModule.GraphicalItems() )
114  {
115  switch( item->Type() )
116  {
117  case PCB_MODULE_TEXT_T:
118  case PCB_MODULE_EDGE_T:
119  Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
120  break;
121 
122  default:
123  wxLogMessage( wxT( "Class MODULE copy constructor internal error: unknown type" ) );
124  break;
125  }
126  }
127 
128  // Copy auxiliary data: 3D_Drawings info
129  m_3D_Drawings = aModule.m_3D_Drawings;
130 
131  m_Doc = aModule.m_Doc;
132  m_KeyWord = aModule.m_KeyWord;
133 
134  m_arflag = 0;
135 
136  // Ensure auxiliary data is up to date
138 
140  new wxArrayString( *aModule.m_initial_comments ) : nullptr;
141 }
142 
143 
145 {
146  // Clean up the owned elements
147  delete m_Reference;
148  delete m_Value;
149  delete m_initial_comments;
150 
151  for( D_PAD* p : m_pads )
152  delete p;
153 
154  m_pads.clear();
155 
157  delete p;
158 
159  m_fp_zones.clear();
160 
161  for( BOARD_ITEM* d : m_drawings )
162  delete d;
163 
164  m_drawings.clear();
165 }
166 
167 
168 MODULE& MODULE::operator=( const MODULE& aOther )
169 {
170  BOARD_ITEM::operator=( aOther );
171 
172  m_Pos = aOther.m_Pos;
173  m_fpid = aOther.m_fpid;
174  m_Attributs = aOther.m_Attributs;
176  m_Orient = aOther.m_Orient;
177  m_BoundaryBox = aOther.m_BoundaryBox;
178  m_CntRot90 = aOther.m_CntRot90;
179  m_CntRot180 = aOther.m_CntRot180;
181  m_Link = aOther.m_Link;
182  m_Path = aOther.m_Path;
183 
190  m_ThermalGap = aOther.m_ThermalGap;
191 
192  // Copy reference and value
193  *m_Reference = *aOther.m_Reference;
194  m_Reference->SetParent( this );
195  *m_Value = *aOther.m_Value;
196  m_Value->SetParent( this );
197 
198  // Copy auxiliary data: Pads
199  m_pads.clear();
200 
201  for( D_PAD* pad : aOther.Pads() )
202  Add( new D_PAD( *pad ) );
203 
204  // Copy auxiliary data: Zones
205  m_fp_zones.clear();
206 
207  for( MODULE_ZONE_CONTAINER* item : aOther.Zones() )
208  {
209  Add( static_cast<MODULE_ZONE_CONTAINER*>( item->Clone() ) );
210 
211  // Ensure the net info is OK and especially uses the net info list
212  // living in the current board
213  // Needed when copying a fp from fp editor that has its own board
214  // Must be NETINFO_LIST::ORPHANED_ITEM for a keepout that has no net.
215  item->SetNetCode( -1 );
216  }
217 
218  // Copy auxiliary data: Drawings
219  m_drawings.clear();
220 
221  for( BOARD_ITEM* item : aOther.GraphicalItems() )
222  {
223  switch( item->Type() )
224  {
225  case PCB_MODULE_TEXT_T:
226  case PCB_MODULE_EDGE_T:
227  Add( static_cast<BOARD_ITEM*>( item->Clone() ) );
228  break;
229 
230  default:
231  wxLogMessage( wxT( "MODULE::operator=() internal error: unknown type" ) );
232  break;
233  }
234  }
235 
236  // Copy auxiliary data: 3D_Drawings info
237  m_3D_Drawings.clear();
238  m_3D_Drawings = aOther.m_3D_Drawings;
239  m_Doc = aOther.m_Doc;
240  m_KeyWord = aOther.m_KeyWord;
241 
242  // Ensure auxiliary data is up to date
244 
245  return *this;
246 }
247 
248 
249 void MODULE::GetContextualTextVars( wxArrayString* aVars ) const
250 {
251  aVars->push_back( wxT( "REFERENCE" ) );
252  aVars->push_back( wxT( "VALUE" ) );
253  aVars->push_back( wxT( "LAYER" ) );
254 }
255 
256 
257 bool MODULE::ResolveTextVar( wxString* token, int aDepth ) const
258 {
259  if( token->IsSameAs( wxT( "REFERENCE" ) ) )
260  {
261  *token = m_Reference->GetShownText( aDepth + 1 );
262  return true;
263  }
264  else if( token->IsSameAs( wxT( "VALUE" ) ) )
265  {
266  *token = m_Value->GetShownText( aDepth + 1 );
267  return true;
268  }
269  else if( token->IsSameAs( wxT( "LAYER" ) ) )
270  {
271  *token = GetLayerName();
272  return true;
273  }
274 
275  return false;
276 }
277 
278 
280 {
281  // Force the ORPHANED dummy net info for all pads.
282  // ORPHANED dummy net does not depend on a board
283  for( auto pad : m_pads )
284  pad->SetNetCode( NETINFO_LIST::ORPHANED );
285 }
286 
287 
288 void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
289 {
290  switch( aBoardItem->Type() )
291  {
292  case PCB_MODULE_TEXT_T:
293  // Only user text can be added this way.
294  assert( static_cast<TEXTE_MODULE*>( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS );
296 
297  case PCB_MODULE_EDGE_T:
298  if( aMode == ADD_MODE::APPEND )
299  m_drawings.push_back( aBoardItem );
300  else
301  m_drawings.push_front( aBoardItem );
302  break;
303 
304  case PCB_PAD_T:
305  if( aMode == ADD_MODE::APPEND )
306  m_pads.push_back( static_cast<D_PAD*>( aBoardItem ) );
307  else
308  m_pads.push_front( static_cast<D_PAD*>( aBoardItem ) );
309  break;
310 
312  if( aMode == ADD_MODE::APPEND )
313  m_fp_zones.push_back( static_cast<MODULE_ZONE_CONTAINER*>( aBoardItem ) );
314  else
315  m_fp_zones.insert( m_fp_zones.begin(), static_cast<MODULE_ZONE_CONTAINER*>( aBoardItem ) );
316  break;
317 
318  default:
319  {
320  wxString msg;
321  msg.Printf( wxT( "MODULE::Add() needs work: BOARD_ITEM type (%d) not handled" ),
322  aBoardItem->Type() );
323  wxFAIL_MSG( msg );
324 
325  return;
326  }
327  }
328 
329  aBoardItem->ClearEditFlags();
330  aBoardItem->SetParent( this );
331 }
332 
333 
334 void MODULE::Remove( BOARD_ITEM* aBoardItem )
335 {
336  switch( aBoardItem->Type() )
337  {
338  case PCB_MODULE_TEXT_T:
339  // Only user text can be removed this way.
340  wxCHECK_RET(
341  static_cast<TEXTE_MODULE*>( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS,
342  "Please report this bug: Invalid remove operation on required text" );
344 
345  case PCB_MODULE_EDGE_T:
346  for( auto it = m_drawings.begin(); it != m_drawings.end(); ++it )
347  {
348  if( *it == aBoardItem )
349  {
350  m_drawings.erase( it );
351  break;
352  }
353  }
354 
355  break;
356 
357  case PCB_PAD_T:
358  for( auto it = m_pads.begin(); it != m_pads.end(); ++it )
359  {
360  if( *it == static_cast<D_PAD*>( aBoardItem ) )
361  {
362  m_pads.erase( it );
363  break;
364  }
365  }
366 
367  break;
368 
370  for( auto it = m_fp_zones.begin(); it != m_fp_zones.end(); ++it )
371  {
372  if( *it == static_cast<MODULE_ZONE_CONTAINER*>( aBoardItem ) )
373  {
374  m_fp_zones.erase( it );
375  break;
376  }
377  }
378 
379  break;
380 
381  default:
382  {
383  wxString msg;
384  msg.Printf( wxT( "MODULE::Remove() needs work: BOARD_ITEM type (%d) not handled" ),
385  aBoardItem->Type() );
386  wxFAIL_MSG( msg );
387  }
388  }
389 }
390 
391 
393 {
395 }
396 
397 
398 double MODULE::GetArea( int aPadding ) const
399 {
400  double w = std::abs( m_BoundaryBox.GetWidth() ) + aPadding;
401  double h = std::abs( m_BoundaryBox.GetHeight() ) + aPadding;
402  return w * h;
403 }
404 
405 
407 {
408  EDA_RECT area;
409 
410  area.SetOrigin( m_Pos );
411  area.SetEnd( m_Pos );
412  area.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the area
413 
414  for( BOARD_ITEM* item : m_drawings )
415  {
416  if( item->Type() == PCB_MODULE_EDGE_T )
417  area.Merge( item->GetBoundingBox() );
418  }
419 
420  for( D_PAD* pad : m_pads )
421  area.Merge( pad->GetBoundingBox() );
422 
423  for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
424  area.Merge( zone->GetBoundingBox() );
425 
426  return area;
427 }
428 
429 
431 {
432  EDA_RECT area;
433 
434  // We want the bounding box of the footprint pads at rot 0, not flipped
435  // Create such a image:
436  MODULE dummy( *this );
437 
438  dummy.SetPosition( wxPoint( 0, 0 ) );
439  if( dummy.IsFlipped() )
440  dummy.Flip( wxPoint( 0, 0 ) , false );
441 
442  if( dummy.GetOrientation() )
443  dummy.SetOrientation( 0 );
444 
445  for( auto pad : dummy.Pads() )
446  area.Merge( pad->GetBoundingBox() );
447 
448  return area;
449 }
450 
451 
453 {
454  EDA_RECT area = GetFootprintRect();
455 
456  // Add in items not collected by GetFootprintRect():
457  for( BOARD_ITEM* item : m_drawings )
458  {
459  if( item->Type() != PCB_MODULE_EDGE_T )
460  area.Merge( item->GetBoundingBox() );
461  }
462 
463  area.Merge( m_Value->GetBoundingBox() );
464  area.Merge( m_Reference->GetBoundingBox() );
465 
466  return area;
467 }
468 
469 
470 const EDA_RECT MODULE::GetBoundingBox( bool aIncludeInvisibleText ) const
471 {
472  EDA_RECT area = GetFootprintRect();
473 
474  // Add in items not collected by GetFootprintRect():
475  for( BOARD_ITEM* item : m_drawings )
476  {
477  if( item->Type() != PCB_MODULE_EDGE_T )
478  area.Merge( item->GetBoundingBox() );
479  }
480 
481  if( m_Value->IsVisible() || aIncludeInvisibleText )
482  area.Merge( m_Value->GetBoundingBox() );
483 
484  if( m_Reference->IsVisible() || aIncludeInvisibleText )
485  area.Merge( m_Reference->GetBoundingBox() );
486 
487  return area;
488 }
489 
490 
506 {
507  SHAPE_POLY_SET poly;
508 
509  double orientation = GetOrientationRadians();
510 
511  MODULE temp = *this;
512  temp.SetOrientation( 0.0 );
513  BOX2I area = temp.GetFootprintRect();
514 
515  poly.NewOutline();
516 
517  VECTOR2I p = area.GetPosition();
518  poly.Append( p );
519  p.x = area.GetRight();
520  poly.Append( p );
521  p.y = area.GetBottom();
522  poly.Append( p );
523  p.x = area.GetX();
524  poly.Append( p );
525 
526  BOARD* board = GetBoard();
527  if( board )
528  {
529  int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue();
530  poly.Inflate( biggest_clearance, 4 );
531  }
532 
533  poly.Inflate( Millimeter2iu( 0.01 ), 4 );
534  poly.Rotate( -orientation, m_Pos );
535 
536  return poly;
537 }
538 
539 
540 void MODULE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
541 {
542  wxString msg, msg2;
543 
544  aList.emplace_back( m_Reference->GetShownText(), m_Value->GetShownText(), DARKCYAN );
545 
546  if( aFrame->IsType( FRAME_FOOTPRINT_VIEWER )
548  || aFrame->IsType( FRAME_FOOTPRINT_EDITOR ) )
549  {
550  wxDateTime date( static_cast<time_t>( m_LastEditTime ) );
551 
552  // Date format: see http://www.cplusplus.com/reference/ctime/strftime
553  if( m_LastEditTime && date.IsValid() )
554  msg = date.Format( wxT( "%b %d, %Y" ) ); // Abbreviated_month_name Day, Year
555  else
556  msg = _( "Unknown" );
557 
558  aList.emplace_back( _( "Last Change" ), msg, BROWN );
559  }
560  else if( aFrame->IsType( FRAME_PCB_EDITOR ) )
561  {
562  aList.emplace_back( _( "Board Side" ), IsFlipped() ? _( "Back (Flipped)" )
563  : _( "Front" ), RED );
564  }
565 
566  msg = wxT( ". ." );
567 
568  if( IsLocked() )
569  msg[0] = 'L';
570 
572  msg[2] = 'P';
573 
574  aList.emplace_back( _( "Status" ), msg, MAGENTA );
575 
576  // Controls on right side of the dialog
577  switch( m_Attributs & 255 )
578  {
579  case 0: msg = _( "Normal" ); break;
580  case MOD_CMS: msg = _( "Insert" ); break;
581  case MOD_VIRTUAL: msg = _( "Virtual" ); break;
582  default: msg = wxT( "???" ); break;
583  }
584 
585  aList.emplace_back( _( "Attributes" ), msg, BROWN );
586 
587  msg.Printf( "%.2f", GetOrientationDegrees() );
588  aList.emplace_back( _( "Rotation" ), msg, BROWN );
589 
590  msg.Printf( _( "Footprint: %s" ),
591  GetChars( m_fpid.Format().c_str() ) );
592  msg2.Printf( _( "3D-Shape: %s" ),
593  m_3D_Drawings.empty() ? _( "none" ) : m_3D_Drawings.front().m_Filename );
594  aList.emplace_back( msg, msg2, BLUE );
595 
596  msg.Printf( _( "Doc: %s" ), m_Doc );
597  msg2.Printf( _( "Keywords: %s" ), m_KeyWord );
598  aList.emplace_back( msg, msg2, BLACK );
599 }
600 
601 
602 bool MODULE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
603 {
604  EDA_RECT rect = m_BoundaryBox;
605  return rect.Inflate( aAccuracy ).Contains( aPosition );
606 }
607 
608 
609 bool MODULE::HitTestAccurate( const wxPoint& aPosition, int aAccuracy ) const
610 {
611  return GetBoundingPoly().Collide( aPosition, aAccuracy );
612 }
613 
614 
615 bool MODULE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
616 {
617  EDA_RECT arect = aRect;
618  arect.Inflate( aAccuracy );
619 
620  if( aContained )
621  return arect.Contains( m_BoundaryBox );
622  else
623  {
624  // If the rect does not intersect the bounding box, skip any tests
625  if( !aRect.Intersects( GetBoundingBox() ) )
626  return false;
627 
628  // Determine if any elements in the MODULE intersect the rect
629  for( D_PAD* pad : m_pads )
630  {
631  if( pad->HitTest( arect, false, 0 ) )
632  return true;
633  }
634 
635  for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
636  {
637  if( zone->HitTest( arect, false, 0 ) )
638  return true;
639  }
640 
641  for( BOARD_ITEM* item : m_drawings )
642  {
643  if( item->HitTest( arect, false, 0 ) )
644  return true;
645  }
646 
647  // No items were hit
648  return false;
649  }
650 }
651 
652 
653 D_PAD* MODULE::FindPadByName( const wxString& aPadName ) const
654 {
655  for( D_PAD* pad : m_pads )
656  {
657  if( pad->GetName() == aPadName )
658  return pad;
659  }
660 
661  return NULL;
662 }
663 
664 
665 D_PAD* MODULE::GetPad( const wxPoint& aPosition, LSET aLayerMask )
666 {
667  for( D_PAD* pad : m_pads )
668  {
669  // ... and on the correct layer.
670  if( !( pad->GetLayerSet() & aLayerMask ).any() )
671  continue;
672 
673  if( pad->HitTest( aPosition ) )
674  return pad;
675  }
676 
677  return NULL;
678 }
679 
680 
682 {
683  D_PAD* topLeftPad = GetFirstPad();
684 
685  for( D_PAD* p : m_pads )
686  {
687  wxPoint pnt = p->GetPosition(); // GetPosition() returns the center of the pad
688 
689  if( ( pnt.x < topLeftPad->GetPosition().x ) ||
690  ( topLeftPad->GetPosition().x == pnt.x && pnt.y < topLeftPad->GetPosition().y ) )
691  {
692  topLeftPad = p;
693  }
694  }
695 
696  return topLeftPad;
697 }
698 
699 
700 unsigned MODULE::GetPadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
701 {
702  if( aIncludeNPTH )
703  return m_pads.size();
704 
705  unsigned cnt = 0;
706 
707  for( D_PAD* pad : m_pads )
708  {
709  if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
710  continue;
711 
712  cnt++;
713  }
714 
715  return cnt;
716 }
717 
718 
719 unsigned MODULE::GetUniquePadCount( INCLUDE_NPTH_T aIncludeNPTH ) const
720 {
721  std::set<wxString> usedNames;
722 
723  // Create a set of used pad numbers
724  for( D_PAD* pad : m_pads )
725  {
726  // Skip pads not on copper layers (used to build complex
727  // solder paste shapes for instance)
728  if( ( pad->GetLayerSet() & LSET::AllCuMask() ).none() )
729  continue;
730 
731  // Skip pads with no name, because they are usually "mechanical"
732  // pads, not "electrical" pads
733  if( pad->GetName().IsEmpty() )
734  continue;
735 
736  if( !aIncludeNPTH )
737  {
738  // skip NPTH
739  if( pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
740  {
741  continue;
742  }
743  }
744 
745  usedNames.insert( pad->GetName() );
746  }
747 
748  return usedNames.size();
749 }
750 
751 
753 {
754  if( NULL == a3DModel )
755  return;
756 
757  if( !a3DModel->m_Filename.empty() )
758  m_3D_Drawings.push_back( *a3DModel );
759 
760  delete a3DModel;
761 }
762 
763 
764 // see class_module.h
765 SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
766 {
767  KICAD_T stype;
769  const KICAD_T* p = scanTypes;
770  bool done = false;
771 
772 #if 0 && defined(DEBUG)
773  std::cout << GetClass().mb_str() << ' ';
774 #endif
775 
776  while( !done )
777  {
778  stype = *p;
779 
780  switch( stype )
781  {
782  case PCB_MODULE_T:
783  result = inspector( this, testData ); // inspect me
784  ++p;
785  break;
786 
787  case PCB_PAD_T:
788  result = IterateForward<D_PAD*>( m_pads, inspector, testData, p );
789  ++p;
790  break;
791 
793  result = IterateForward<MODULE_ZONE_CONTAINER*>( m_fp_zones, inspector, testData, p );
794  ++p;
795  break;
796 
797  case PCB_MODULE_TEXT_T:
798  result = inspector( m_Reference, testData );
799 
800  if( result == SEARCH_RESULT::QUIT )
801  break;
802 
803  result = inspector( m_Value, testData );
804 
805  if( result == SEARCH_RESULT::QUIT )
806  break;
807 
808  // Intentionally fall through since m_Drawings can hold TYPETEXTMODULE also
810 
811  case PCB_MODULE_EDGE_T:
812  result = IterateForward<BOARD_ITEM*>( m_drawings, inspector, testData, p );
813 
814  // skip over any types handled in the above call.
815  for( ; ; )
816  {
817  switch( stype = *++p )
818  {
819  case PCB_MODULE_TEXT_T:
820  case PCB_MODULE_EDGE_T:
821  continue;
822 
823  default:
824  ;
825  }
826 
827  break;
828  }
829 
830  break;
831 
832  default:
833  done = true;
834  break;
835  }
836 
837  if( result == SEARCH_RESULT::QUIT )
838  break;
839  }
840 
841  return result;
842 }
843 
844 
845 wxString MODULE::GetSelectMenuText( EDA_UNITS aUnits ) const
846 {
847  wxString reference = GetReference();
848 
849  if( reference.IsEmpty() )
850  reference = _( "<no reference designator>" );
851 
852  return wxString::Format( _( "Footprint %s on %s" ), reference, GetLayerName() );
853 }
854 
855 
857 {
858  return module_xpm;
859 }
860 
861 
863 {
864  return new MODULE( *this );
865 }
866 
867 
868 void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
869 {
870  try
871  {
872  for( D_PAD* pad : m_pads )
873  aFunction( static_cast<BOARD_ITEM*>( pad ) );
874 
875  for( MODULE_ZONE_CONTAINER* zone : m_fp_zones )
876  aFunction( static_cast<MODULE_ZONE_CONTAINER*>( zone ) );
877 
878  for( BOARD_ITEM* drawing : m_drawings )
879  aFunction( static_cast<BOARD_ITEM*>( drawing ) );
880 
881  aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
882  aFunction( static_cast<BOARD_ITEM*>( m_Value ) );
883  }
884  catch( std::bad_function_call& )
885  {
886  DisplayError( NULL, wxT( "Error running MODULE::RunOnChildren" ) );
887  }
888 }
889 
890 
891 void MODULE::GetAllDrawingLayers( int aLayers[], int& aCount, bool aIncludePads ) const
892 {
893  std::unordered_set<int> layers;
894 
895  for( BOARD_ITEM* item : m_drawings )
896  layers.insert( static_cast<int>( item->GetLayer() ) );
897 
898  if( aIncludePads )
899  {
900  for( D_PAD* pad : m_pads )
901  {
902  int pad_layers[KIGFX::VIEW::VIEW_MAX_LAYERS], pad_layers_count;
903  pad->ViewGetLayers( pad_layers, pad_layers_count );
904 
905  for( int i = 0; i < pad_layers_count; i++ )
906  layers.insert( pad_layers[i] );
907  }
908  }
909 
910  aCount = layers.size();
911  int i = 0;
912 
913  for( int layer : layers )
914  aLayers[i++] = layer;
915 }
916 
917 
918 void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const
919 {
920  aCount = 2;
921  aLayers[0] = LAYER_ANCHOR;
922 
923  switch( m_Layer )
924  {
925  default:
926  wxASSERT_MSG( false, "Illegal layer" ); // do you really have modules placed on other layers?
928 
929  case F_Cu:
930  aLayers[1] = LAYER_MOD_FR;
931  break;
932 
933  case B_Cu:
934  aLayers[1] = LAYER_MOD_BK;
935  break;
936  }
937 
938  // If there are no pads, and only drawings on a silkscreen layer, then
939  // report the silkscreen layer as well so that the component can be edited
940  // with the silkscreen layer
941  bool f_silk = false, b_silk = false, non_silk = false;
942 
943  for( auto item : m_drawings )
944  {
945  if( item->GetLayer() == F_SilkS )
946  f_silk = true;
947  else if( item->GetLayer() == B_SilkS )
948  b_silk = true;
949  else
950  non_silk = true;
951  }
952 
953  if( ( f_silk || b_silk ) && !non_silk && m_pads.empty() )
954  {
955  if( f_silk )
956  aLayers[ aCount++ ] = F_SilkS;
957 
958  if( b_silk )
959  aLayers[ aCount++ ] = B_SilkS;
960  }
961 }
962 
963 
964 unsigned int MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
965 {
966  int layer = ( m_Layer == F_Cu ) ? LAYER_MOD_FR :
968 
969  // Currently it is only for anchor layer
970  if( aView->IsLayerVisible( layer ) )
971  return 3;
972 
973  return std::numeric_limits<unsigned int>::max();
974 }
975 
976 
977 const BOX2I MODULE::ViewBBox() const
978 {
979  EDA_RECT area = GetFootprintRect();
980 
981  // Calculate extended area including text fields
982  area.Merge( m_Reference->GetBoundingBox() );
983  area.Merge( m_Value->GetBoundingBox() );
984 
985  // Add the Clearance shape size: (shape around the pads when the
986  // clearance is shown. Not optimized, but the draw cost is small
987  // (perhaps smaller than optimization).
988  BOARD* board = GetBoard();
989  if( board )
990  {
991  int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue();
992  area.Inflate( biggest_clearance );
993  }
994 
995  return area;
996 }
997 
998 
999 bool MODULE::IsLibNameValid( const wxString & aName )
1000 {
1001  const wxChar * invalids = StringLibNameInvalidChars( false );
1002 
1003  if( aName.find_first_of( invalids ) != std::string::npos )
1004  return false;
1005 
1006  return true;
1007 }
1008 
1009 
1010 const wxChar* MODULE::StringLibNameInvalidChars( bool aUserReadable )
1011 {
1012  // This list of characters is also duplicated in validators.cpp and
1013  // lib_id.cpp
1014  // TODO: Unify forbidden character lists
1015  static const wxChar invalidChars[] = wxT("%$<>\t\n\r\"\\/:");
1016  static const wxChar invalidCharsReadable[] = wxT("% $ < > 'tab' 'return' 'line feed' \\ \" / :");
1017 
1018  if( aUserReadable )
1019  return invalidCharsReadable;
1020  else
1021  return invalidChars;
1022 }
1023 
1024 
1025 void MODULE::Move( const wxPoint& aMoveVector )
1026 {
1027  wxPoint newpos = m_Pos + aMoveVector;
1028  SetPosition( newpos );
1029 }
1030 
1031 
1032 void MODULE::Rotate( const wxPoint& aRotCentre, double aAngle )
1033 {
1034  double orientation = GetOrientation();
1035  double newOrientation = orientation + aAngle;
1036  wxPoint newpos = m_Pos;
1037  RotatePoint( &newpos, aRotCentre, aAngle );
1038  SetPosition( newpos );
1039  SetOrientation( newOrientation );
1040 
1041  m_Reference->KeepUpright( orientation, newOrientation );
1042  m_Value->KeepUpright( orientation, newOrientation );
1043 
1044  for( BOARD_ITEM* item : m_drawings )
1045  {
1046  if( item->Type() == PCB_MODULE_TEXT_T )
1047  static_cast<TEXTE_MODULE*>( item )->KeepUpright( orientation, newOrientation );
1048  }
1049 }
1050 
1051 
1052 void MODULE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
1053 {
1054  // Move module to its final position:
1055  wxPoint finalPos = m_Pos;
1056 
1057  // Now Flip the footprint.
1058  // Flipping a footprint is a specific transform:
1059  // it is not mirrored like a text.
1060  // We have to change the side, and ensure the footprint rotation is
1061  // modified accordint to the transform, because this parameter is used
1062  // in pick and place files, and when updating the footprint from library.
1063  // When flipped around the X axis (Y coordinates changed) orientation is negated
1064  // When flipped around the Y axis (X coordinates changed) orientation is 180 - old orient.
1065  // Because it is specfic to a footprint, we flip around the X axis, and after rotate 180 deg
1066 
1067  MIRROR( finalPos.y, aCentre.y );
1068 
1069  SetPosition( finalPos );
1070 
1071  // Flip layer
1072  SetLayer( FlipLayer( GetLayer() ) );
1073 
1074  // Reverse mirror orientation.
1075  m_Orient = -m_Orient;
1076 
1078 
1079  // Mirror pads to other side of board.
1080  for( auto pad : m_pads )
1081  pad->Flip( m_Pos, false );
1082 
1083  // Mirror zones to other side of board.
1084  for( auto zone : m_fp_zones )
1085  zone->Flip( m_Pos, aFlipLeftRight );
1086 
1087  // Mirror reference and value.
1088  m_Reference->Flip( m_Pos, false );
1089  m_Value->Flip( m_Pos, false );
1090 
1091  // Reverse mirror module graphics and texts.
1092  for( auto item : m_drawings )
1093  {
1094  switch( item->Type() )
1095  {
1096  case PCB_MODULE_EDGE_T:
1097  static_cast<EDGE_MODULE*>( item )->Flip( m_Pos, false );
1098  break;
1099 
1100  case PCB_MODULE_TEXT_T:
1101  static_cast<TEXTE_MODULE*>( item )->Flip( m_Pos, false );
1102  break;
1103 
1104  default:
1105  wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) );
1106  break;
1107  }
1108  }
1109 
1110  // Now rotate 180 deg if required
1111  if( aFlipLeftRight )
1112  Rotate( aCentre, 1800.0 );
1113 
1115 }
1116 
1117 
1118 void MODULE::SetPosition( const wxPoint& newpos )
1119 {
1120  wxPoint delta = newpos - m_Pos;
1121 
1122  m_Pos += delta;
1123 
1124  m_Reference->EDA_TEXT::Offset( delta );
1125  m_Value->EDA_TEXT::Offset( delta );
1126 
1127  for( auto pad : m_pads )
1128  {
1129  pad->SetPosition( pad->GetPosition() + delta );
1130  }
1131 
1132  for( auto zone : m_fp_zones )
1133  zone->Move( delta );
1134 
1135  for( auto item : m_drawings )
1136  {
1137  switch( item->Type() )
1138  {
1139  case PCB_MODULE_EDGE_T:
1140  {
1141  EDGE_MODULE* pt_edgmod = (EDGE_MODULE*) item;
1142  pt_edgmod->SetDrawCoord();
1143  break;
1144  }
1145 
1146  case PCB_MODULE_TEXT_T:
1147  {
1148  TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
1149  text->EDA_TEXT::Offset( delta );
1150  break;
1151  }
1152 
1153  default:
1154  wxMessageBox( wxT( "Draw type undefined." ) );
1155  break;
1156  }
1157  }
1158 
1160 }
1161 
1162 
1163 void MODULE::MoveAnchorPosition( const wxPoint& aMoveVector )
1164 {
1165  /* Move the reference point of the footprint
1166  * the footprints elements (pads, outlines, edges .. ) are moved
1167  * but:
1168  * - the footprint position is not modified.
1169  * - the relative (local) coordinates of these items are modified
1170  * - Draw coordinates are updated
1171  */
1172 
1173 
1174  // Update (move) the relative coordinates relative to the new anchor point.
1175  wxPoint moveVector = aMoveVector;
1176  RotatePoint( &moveVector, -GetOrientation() );
1177 
1178  // Update of the reference and value.
1179  m_Reference->SetPos0( m_Reference->GetPos0() + moveVector );
1181  m_Value->SetPos0( m_Value->GetPos0() + moveVector );
1182  m_Value->SetDrawCoord();
1183 
1184  // Update the pad local coordinates.
1185  for( auto pad : m_pads )
1186  {
1187  pad->SetPos0( pad->GetPos0() + moveVector );
1188  pad->SetDrawCoord();
1189  }
1190 
1191  // Update the draw element coordinates.
1192  for( auto item : GraphicalItems() )
1193  {
1194  switch( item->Type() )
1195  {
1196  case PCB_MODULE_EDGE_T:
1197  {
1198  EDGE_MODULE* edge = static_cast<EDGE_MODULE*>( item );
1199  edge->Move( moveVector );
1200  }
1201  break;
1202 
1203  case PCB_MODULE_TEXT_T:
1204  {
1205  TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( item );
1206  text->SetPos0( text->GetPos0() + moveVector );
1207  text->SetDrawCoord();
1208  }
1209  break;
1210 
1211  default:
1212  break;
1213  }
1214  }
1215 
1217 }
1218 
1219 
1220 void MODULE::SetOrientation( double newangle )
1221 {
1222  double angleChange = newangle - m_Orient; // change in rotation
1223 
1224  NORMALIZE_ANGLE_180( newangle );
1225 
1226  m_Orient = newangle;
1227 
1228  for( auto pad : m_pads )
1229  {
1230  pad->SetOrientation( pad->GetOrientation() + angleChange );
1231  pad->SetDrawCoord();
1232  }
1233 
1234  for( auto zone : m_fp_zones )
1235  {
1236  zone->Rotate( GetPosition(), angleChange );
1237  }
1238 
1239  // Update of the reference and value.
1241  m_Value->SetDrawCoord();
1242 
1243  // Displace contours and text of the footprint.
1244  for( auto item : m_drawings )
1245  {
1246  if( item->Type() == PCB_MODULE_EDGE_T )
1247  {
1248  static_cast<EDGE_MODULE*>( item )->SetDrawCoord();
1249  }
1250  else if( item->Type() == PCB_MODULE_TEXT_T )
1251  {
1252  static_cast<TEXTE_MODULE*>( item )->SetDrawCoord();
1253  }
1254  }
1255 
1257 }
1258 
1259 
1260 BOARD_ITEM* MODULE::DuplicateItem( const BOARD_ITEM* aItem, bool aAddToModule )
1261 {
1262  BOARD_ITEM* new_item = NULL;
1263  MODULE_ZONE_CONTAINER* new_zone = NULL;
1264 
1265  switch( aItem->Type() )
1266  {
1267  case PCB_PAD_T:
1268  {
1269  D_PAD* new_pad = new D_PAD( *static_cast<const D_PAD*>( aItem ) );
1270 
1271  if( aAddToModule )
1272  m_pads.push_back( new_pad );
1273 
1274  new_item = new_pad;
1275  break;
1276  }
1277 
1279  {
1280  new_zone = new MODULE_ZONE_CONTAINER( *static_cast<const MODULE_ZONE_CONTAINER*>( aItem ) );
1281 
1282  if( aAddToModule )
1283  m_fp_zones.push_back( new_zone );
1284 
1285  new_item = new_zone;
1286  break;
1287  }
1288 
1289  case PCB_MODULE_TEXT_T:
1290  {
1291  TEXTE_MODULE* new_text = new TEXTE_MODULE( *static_cast<const TEXTE_MODULE*>( aItem ) );
1292 
1293  if( new_text->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE )
1294  {
1295  new_text->SetText( wxT( "${REFERENCE}" ) );
1297  }
1298  else if( new_text->GetType() == TEXTE_MODULE::TEXT_is_VALUE )
1299  {
1300  new_text->SetText( wxT( "${VALUE}" ) );
1302  }
1303 
1304  if( aAddToModule )
1305  Add( new_text );
1306 
1307  new_item = new_text;
1308 
1309  break;
1310  }
1311 
1312  case PCB_MODULE_EDGE_T:
1313  {
1314  EDGE_MODULE* new_edge = new EDGE_MODULE( *static_cast<const EDGE_MODULE*>(aItem) );
1315 
1316  if( aAddToModule )
1317  Add( new_edge );
1318 
1319  new_item = new_edge;
1320  break;
1321  }
1322 
1323  case PCB_MODULE_T:
1324  // Ignore the module itself
1325  break;
1326 
1327  default:
1328  // Un-handled item for duplication
1329  wxFAIL_MSG( "Duplication not supported for items of class " + aItem->GetClass() );
1330  break;
1331  }
1332 
1333  return new_item;
1334 }
1335 
1336 
1337 wxString MODULE::GetNextPadName( const wxString& aLastPadName ) const
1338 {
1339  std::set<wxString> usedNames;
1340 
1341  // Create a set of used pad numbers
1342  for( D_PAD* pad : m_pads )
1343  usedNames.insert( pad->GetName() );
1344 
1345  wxString prefix = UTIL::GetReferencePrefix( aLastPadName );
1346  int num = GetTrailingInt( aLastPadName );
1347 
1348  while( usedNames.count( wxString::Format( "%s%d", prefix, num ) ) )
1349  num++;
1350 
1351  return wxString::Format( "%s%d", prefix, num );
1352 }
1353 
1354 
1355 void MODULE::IncrementReference( int aDelta )
1356 {
1357  const auto& refdes = GetReference();
1358  SetReference( wxString::Format( wxT( "%s%i" ), UTIL::GetReferencePrefix( refdes ),
1359  GetTrailingInt( refdes ) + aDelta ) );
1360 }
1361 
1362 
1363 // Calculate the area of aPolySet, after fracturation, because
1364 // polygons with no hole are expected.
1365 static double polygonArea( SHAPE_POLY_SET& aPolySet )
1366 {
1367  double area = 0.0;
1368  for( int ii = 0; ii < aPolySet.OutlineCount(); ii++ )
1369  {
1370  SHAPE_LINE_CHAIN& outline = aPolySet.Outline( ii );
1371  // Ensure the curr outline is closed, to calculate area
1372  outline.SetClosed( true );
1373 
1374  area += outline.Area();
1375  }
1376 
1377  return area;
1378 }
1379 
1380 // a helper function to add a rectangular polygon aRect to aPolySet
1381 static void addRect( SHAPE_POLY_SET& aPolySet, wxRect aRect )
1382 {
1383  aPolySet.NewOutline();
1384 
1385  aPolySet.Append( aRect.GetX(), aRect.GetY() );
1386  aPolySet.Append( aRect.GetX()+aRect.width, aRect.GetY() );
1387  aPolySet.Append( aRect.GetX()+aRect.width, aRect.GetY()+aRect.height );
1388  aPolySet.Append( aRect.GetX(), aRect.GetY()+aRect.height );
1389 }
1390 
1391 double MODULE::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
1392 {
1393  double moduleArea = GetFootprintRect().GetArea();
1394  SHAPE_POLY_SET coveredRegion;
1395  addRect( coveredRegion, GetFootprintRect() );
1396 
1397  // build list of holes (covered areas not available for selection)
1398  SHAPE_POLY_SET holes;
1399 
1400  for( auto pad : m_pads )
1401  addRect( holes, pad->GetBoundingBox() );
1402 
1403  addRect( holes, m_Reference->GetBoundingBox() );
1404  addRect( holes, m_Value->GetBoundingBox() );
1405 
1406  for( int i = 0; i < aCollector.GetCount(); ++i )
1407  {
1408  BOARD_ITEM* item = aCollector[i];
1409 
1410  switch( item->Type() )
1411  {
1412  case PCB_TEXT_T:
1413  case PCB_MODULE_TEXT_T:
1414  case PCB_TRACE_T:
1415  case PCB_ARC_T:
1416  case PCB_VIA_T:
1417  addRect( holes, item->GetBoundingBox() );
1418  break;
1419  default:
1420  break;
1421  }
1422  }
1423 
1424  SHAPE_POLY_SET uncoveredRegion;
1425 
1426  try
1427  {
1428  uncoveredRegion.BooleanSubtract( coveredRegion, holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1429  uncoveredRegion.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1430  uncoveredRegion.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1431  }
1432  catch( ClipperLib::clipperException& )
1433  {
1434  // better to be conservative (this will result in the disambiguate dialog)
1435  return 1.0;
1436  }
1437 
1438  double uncoveredRegionArea = polygonArea( uncoveredRegion );
1439  double coveredArea = moduleArea - uncoveredRegionArea;
1440  double ratio = ( coveredArea / moduleArea );
1441 
1442  return std::min( ratio, 1.0 );
1443 }
1444 
1445 
1446 // see convert_drawsegment_list_to_polygon.cpp:
1447 extern bool ConvertOutlineToPolygon( std::vector<DRAWSEGMENT*>& aSegList, SHAPE_POLY_SET& aPolygons,
1448  wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation = nullptr );
1449 
1451 {
1454  // Build the courtyard area from graphic items on the courtyard.
1455  // Only PCB_MODULE_EDGE_T have meaning, graphic texts are ignored.
1456  // Collect items:
1457  std::vector< DRAWSEGMENT* > list_front;
1458  std::vector< DRAWSEGMENT* > list_back;
1459 
1460  for( auto item : GraphicalItems() )
1461  {
1462  if( item->GetLayer() == B_CrtYd && item->Type() == PCB_MODULE_EDGE_T )
1463  list_back.push_back( static_cast< DRAWSEGMENT* > ( item ) );
1464 
1465  if( item->GetLayer() == F_CrtYd && item->Type() == PCB_MODULE_EDGE_T )
1466  list_front.push_back( static_cast< DRAWSEGMENT* > ( item ) );
1467  }
1468 
1469  // Note: if no item found on courtyard layers, return true.
1470  // false is returned only when the shape defined on courtyard layers
1471  // is not convertible to a polygon
1472  if( !list_front.size() && !list_back.size() )
1473  return true;
1474 
1475  wxString error_msg;
1476 
1477  #define ARC_ERROR_MAX 0.02 /* error max in mm to approximate a arc by segments */
1478  bool success = ConvertOutlineToPolygon( list_front, m_poly_courtyard_front,
1479  &error_msg,
1480  (unsigned) Millimeter2iu( ARC_ERROR_MAX ) );
1481 
1482  if( success )
1483  {
1484  success = ConvertOutlineToPolygon( list_back, m_poly_courtyard_back,
1485  &error_msg,
1486  (unsigned) Millimeter2iu( ARC_ERROR_MAX ) );
1487  }
1488 
1489  if( !error_msg.IsEmpty() )
1490  {
1491  wxLogMessage( wxString::Format( _( "Processing courtyard of \"%s\": %s" ),
1492  GetChars( GetFPID().Format() ),
1493  error_msg) );
1494  }
1495 
1496  return success;
1497 }
1498 
1499 
1501 {
1502  assert( aImage->Type() == PCB_MODULE_T );
1503 
1504  std::swap( *((MODULE*) this), *((MODULE*) aImage) );
1505 }
1506 
1507 
1509 {
1510  // returns true if the given module has at lesat one non smd pin, such as through hole
1511 
1512  for( auto pad : Pads() )
1513  {
1514  if( pad->GetAttribute() != PAD_ATTRIB_SMD )
1515  return true;
1516  }
1517 
1518  return false;
1519 }
1520 
1521 
1522 static struct MODULE_DESC
1523 {
1525  {
1526  wxPGChoices fpLayers; // footprints might be placed only on F.Cu & B.Cu
1527  fpLayers.Add( LSET::Name( F_Cu ), F_Cu );
1528  fpLayers.Add( LSET::Name( B_Cu ), B_Cu );
1529 
1531  REGISTER_TYPE( MODULE );
1536 
1537  auto layer = new PROPERTY_ENUM<MODULE, PCB_LAYER_ID, BOARD_ITEM>( _( "Layer" ),
1539  layer->SetChoices( fpLayers );
1540  propMgr.ReplaceProperty( TYPE_HASH( BOARD_ITEM ), _( "Layer" ), layer );
1541 
1542  propMgr.AddProperty( new PROPERTY<MODULE, wxString>( _( "Reference" ),
1544  propMgr.AddProperty( new PROPERTY<MODULE, wxString>( _( "Value" ),
1546  propMgr.AddProperty( new PROPERTY<MODULE, double>( _( "Orientation" ),
1548  //propMgr.AddProperty( new PROPERTY<MODULE, int>( _( "Local Clearance" ),
1549 // &MODULE::SetLocalClearance, &MODULE::GetLocalClearance, PROPERTY_DISPLAY::DISTANCE ) );
1550  propMgr.AddProperty( new PROPERTY<MODULE, int>( _( "Local Solderpaste Margin" ),
1552  propMgr.AddProperty( new PROPERTY<MODULE, double>( _( "Local Solderpaste Margin Ratio" ),
1554  propMgr.AddProperty( new PROPERTY<MODULE, int>( _( "Thermal Width" ),
1556  propMgr.AddProperty( new PROPERTY<MODULE, int>( _( "Thermal Gap" ),
1558  // TODO zone connection, FPID?
1559  }
1560 } _MODULE_DESC;
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetPadCount returns the number of pads.
LIB_ID m_fpid
Definition: class_module.h:686
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:712
Display value expressed in degrees.
Definition: property.h:48
EDA_UNITS
Definition: common.h:198
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:239
bool BuildPolyCourtyard()
Builds a complex polygon of the courtyard area from graphic items on the courtyard layer.
double GetOrientation() const
Definition: class_module.h:211
double GetArea(int aPadding=0) const
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:61
#define TYPE_HASH(x)
Macro to generate unique identifier for a type
Definition: property.h:53
const BITMAP_OPAQUE module_xpm[1]
Definition: module.cpp:29
void SetThermalGap(int aGap)
Definition: class_module.h:252
int m_CntRot90
Definition: class_module.h:705
#define KI_FALLTHROUGH
int OutlineCount() const
Returns the number of outlines in the set
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Function Rotate Rotate this object.
unsigned GetUniquePadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetUniquePadCount returns the number of unique pads.
SHAPE_POLY_SET m_poly_courtyard_back
Definition: class_module.h:714
PNG memory record (file in memory).
Definition: bitmap_def.h:29
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
void KeepUpright(double aOldOrientation, double aNewOrientation)
Called when rotating the parent footprint.
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
bool IsFlipped() const
function IsFlipped
Definition: class_module.h:288
wxString m_KeyWord
Definition: class_module.h:700
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
This file is part of the common library.
coord_type GetX() const
Definition: box2.h:189
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
void GetAllDrawingLayers(int aLayers[], int &aCount, bool aIncludePads=true) const
Returns a set of all layers that this module has drawings on similar to ViewGetLayers()
SHAPE_POLY_SET GetBoundingPoly() const
Returns a bounding polygon for the shapes and pads in the module This operation is slower but more ac...
bool ConvertOutlineToPolygon(std::vector< DRAWSEGMENT * > &aSegList, SHAPE_POLY_SET &aPolygons, wxString *aErrorText, unsigned int aTolerance, wxPoint *aErrorLocation=nullptr)
Function ConvertOutlineToPolygon build a polygon (with holes) from a DRAWSEGMENT list,...
int m_ThermalWidth
Definition: class_module.h:692
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
wxPoint GetPosition() const override
Definition: class_pad.h:162
double CoverageRatio(const GENERAL_COLLECTOR &aCollector) const
Function CoverageRatio Calculates the ratio of total area of the footprint pads and graphical items t...
anchor of items having an anchor point (texts, footprints)
static double polygonArea(SHAPE_POLY_SET &aPolySet)
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
double m_LocalSolderPasteMarginRatio
Definition: class_module.h:697
bool IsVisible() const
Definition: eda_text.h:185
void GetContextualTextVars(wxArrayString *aVars) const
Return the list of system text vars for this footprint.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Function FlippedLayerNumber.
Definition: lset.cpp:485
int m_LocalSolderPasteMargin
Definition: class_module.h:696
int m_ThermalGap
Definition: class_module.h:693
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
Collection of utility functions for component reference designators (refdes)
int GetWidth() const
Definition: eda_rect.h:119
PADS & Pads()
Definition: class_module.h:169
const wxString GetValue() const
Function GetValue.
Definition: class_module.h:458
bool HasNonSMDPins() const
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:68
Definition: color4d.h:61
KIID_PATH m_Path
Definition: class_module.h:701
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
coord_type GetRight() const
Definition: box2.h:198
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:131
PADS m_pads
Definition: class_module.h:678
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text.
MODULE(BOARD *parent)
void SetOrientationDegrees(double aOrientation)
Definition: class_module.h:210
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
void Add3DModel(MODULE_3D_SETTINGS *a3DModel)
Function Add3DModel adds a3DModel definition to the end of the 3D model list.
const LIB_ID & GetFPID() const
Definition: class_module.h:215
#define ARC_ERROR_MAX
D_PAD * GetFirstPad() const
Gets the first pad in the list or NULL if none.
Definition: class_module.h:505
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Function Rotate rotates all vertices by a given angle.
static const wxChar * StringLibNameInvalidChars(bool aUserReadable)
static function StringLibNameInvalidChars Test for validity of the name in a library of the footprint...
Definition: color4d.h:44
void NORMALIZE_ANGLE_180(T &Angle)
Definition: trigo.h:354
DRAWINGS & GraphicalItems()
Definition: class_module.h:179
coord_type GetBottom() const
Definition: box2.h:199
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
The base class for create windows for drawing purpose.
void MoveAnchorPosition(const wxPoint &aMoveVector)
Function MoveAnchorPosition Move the reference point of the footprint It looks like a move footprint:...
wxArrayString * m_initial_comments
leading s-expression comments in the module, lazily allocated only if needed for speed
Definition: class_module.h:708
void SetLocalSolderPasteMarginRatio(double aRatio)
Definition: class_module.h:244
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names
Definition: property_mgr.h:244
bool Contains(const wxPoint &aPoint) const
Function Contains.
#define MODULE_PADS_LOCKED
In autoplace: module waiting for autoplace.
Definition: class_module.h:294
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
virtual void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:196
static constexpr int VIEW_MAX_LAYERS
maximum number of layers that may be shown
Definition: view.h:701
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
wxString m_Doc
Definition: class_module.h:699
timestamp_t m_LastEditTime
Definition: class_module.h:702
static struct MODULE_DESC _MODULE_DESC
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:433
const char * c_str() const
Definition: utf8.h:107
#define MODULE_is_PLACED
In autoplace: module automatically placed.
Definition: class_module.h:292
show modules on front
int m_LocalClearance
Definition: class_module.h:694
const INSPECTOR_FUNC & INSPECTOR
Definition: base_struct.h:105
PCB_LAYER_ID m_Layer
double m_Orient
Definition: class_module.h:682
void MIRROR(T &aPoint, const T &aMirrorRef)
Definition: macros.h:175
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:101
static void addRect(SHAPE_POLY_SET &aPolySet, wxRect aRect)
class MODULE, a footprint
Definition: typeinfo.h:89
void SetClosed(bool aClosed)
Function SetClosed()
void ClearAllNets()
Function ClearAllNets Clear (i.e.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
virtual void ViewGetLayers(int aLayers[], int &aCount) const override
Function ViewGetLayers() Returns the all the layers within the VIEW the object is painted on.
D_PAD * FindPadByName(const wxString &aPadName) const
Function FindPadByName returns a D_PAD* with a matching name.
Display value expressed in distance units (mm/inch)
Definition: property.h:47
EDA_RECT m_BoundaryBox
Definition: class_module.h:689
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
LSET is a set of PCB_LAYER_IDs.
EDA_RECT GetFpPadsLocalBbox() const
Returns the bounding box containing pads when the footprint is on the front side, orientation 0,...
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:116
#define NULL
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Function Name returns the fixed name association with aLayerId.
Definition: lset.cpp:78
SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
void SetEnd(int x, int y)
Definition: eda_rect.h:192
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Function Flip Flip this object, i.e.
TEXT_TYPE GetType() const
ZONE_CONNECTION m_ZoneConnection
Definition: class_module.h:691
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
virtual const BOX2I ViewBBox() const override
Function ViewBBox() returns the bounding box of the item covering all its layers.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declares an inheritance relationship between types.
void SetThermalWidth(int aWidth)
Definition: class_module.h:249
int m_LocalSolderMaskMargin
Definition: class_module.h:695
std::list< MODULE_3D_SETTINGS > m_3D_Drawings
Definition: class_module.h:680
double GetOrientationRadians() const
Definition: class_module.h:213
int m_arflag
Definition: class_module.h:703
double GetOrientationDegrees() const
Definition: class_module.h:212
MODULE_ZONE_CONTAINERS m_fp_zones
Definition: class_module.h:679
wxString GetNextPadName(const wxString &aLastPadName) const
Function GetNextPadName returns the next available pad name in the module.
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
void SetReference(const wxString &aReference)
Function SetReference.
Definition: class_module.h:443
EDA_ITEM * Clone() const override
Function Clone creates a duplicate of this item with linked list members set to NULL.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
SHAPE_POLY_SET m_poly_courtyard_front
Used in DRC to test the courtyard area (a polygon which can be not basic Note also a footprint can ha...
Definition: class_module.h:713
virtual void SetPosition(const wxPoint &aPos) override
void Remove(BOARD_ITEM *aItem) override
virtual unsigned int ViewGetLOD(int aLayer, KIGFX::VIEW *aView) const override
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
void SetPosition(const wxPoint &aPos) override
double GetArea() const
Function GetArea returns the area of the rectangle.
BOARD_ITEM * DuplicateItem(const BOARD_ITEM *aItem, bool aAddToModule=false)
Function DuplicateItem Duplicate a given item within the module, optionally adding it to the board.
int NewOutline()
Creates a new empty polygon in the set and returns its index
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:297
Definition: color4d.h:59
void SetType(TEXT_TYPE aType)
DRAWINGS m_drawings
Definition: class_module.h:677
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Operator assignment is used to assign the members of aItem to another object.
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
const MODULE_ZONE_CONTAINERS & Zones() const
Definition: class_module.h:184
int GetHeight() const
Definition: eda_rect.h:120
D_PAD * GetTopLeftPad()
void SetPos0(const wxPoint &aPos)
UTF8 Format() const
Definition: lib_id.cpp:237
bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr) const override
Function Collide Checks whether the point aP is either inside or on the edge of the polygon set.
int GetLocalSolderPasteMargin() const
Definition: class_module.h:240
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:480
MODULE & operator=(const MODULE &aOther)
wxString m_Filename
The 3D shape filename in 3D library.
Definition: class_module.h:96
default
Definition: class_module.h:67
BITMAP_DEF GetMenuImage() const override
Function GetMenuImage returns a pointer to an image to be used in menus.
const wxPoint & GetPos0() const
const Vec & GetPosition() const
Definition: box2.h:193
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
static bool IsLibNameValid(const wxString &aName)
static function IsLibNameValid Test for validity of a name of a footprint to be used in a footprint l...
bool HitTestAccurate(const wxPoint &aPosition, int aAccuracy=0) const
Tests if a point is inside the bounding polygon of the module.
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip entity during module flip.
D_PAD * GetPad(const wxPoint &aPosition, LSET aLayerMask=LSET::AllLayersMask())
Function GetPad get a pad at aPosition on aLayerMask in the footprint.
void SetLocalSolderPasteMargin(int aMargin)
Definition: class_module.h:241
Definition: color4d.h:56
double GetLocalSolderPasteMarginRatio() const
Definition: class_module.h:243
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
int m_CntRot180
Definition: class_module.h:706
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
virtual wxString GetClass() const =0
Function GetClass returns the class name.
bool IsType(FRAME_T aType) const
wxString GetReferencePrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void IncrementReference(int aDelta)
Function IncrementReference Bumps the current reference by aDelta.
SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[]) override
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
#define _(s)
Definition: 3d_actions.cpp:33
int m_ModuleStatus
Definition: class_module.h:688
SHAPE_LINE_CHAIN.
void Move(const wxPoint &aMoveVector) override
Function Move move this object.
void SetOrientation(double newangle)
Virtual component: when created by copper shapes on board (Like edge card connectors,...
Definition: class_module.h:70
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
void Move(const wxPoint &aMoveVector) override
Move an edge of the footprint.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Registers a type converter.
void AddProperty(PROPERTY_BASE *aProperty)
Registers a property.
wxString GetClass() const override
Function GetClass returns the class name.
Definition: class_module.h:572
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
void SetDrawCoord()
Set absolute coordinates.
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void SetValue(const wxString &aValue)
Function SetValue.
Definition: class_module.h:467
TEXTE_MODULE * m_Value
Definition: class_module.h:685
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:159
MODULE_ZONE_CONTAINER is the same item as ZONE_CONTAINER, but with a specific type id ZONE_CONTAINER ...
Definition: class_zone.h:952
wxPoint m_Pos
Definition: class_module.h:683
int GetTrailingInt(const wxString &aStr)
Gets the trailing int, if any, from a string.
Definition: string.cpp:684
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
void ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew)
Replaces an existing property for a specific type.
Provides class metadata.
Definition: property_mgr.h:58
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
TEXTE_MODULE * m_Reference
Definition: class_module.h:684
wxPoint GetPosition() const override
Definition: class_module.h:206
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
Abstract interface for BOARD_ITEMs capable of storing other items inside.
virtual const EDA_RECT GetBoundingBox() const
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: base_struct.cpp:97
class ZONE_CONTAINER, managed by a footprint
Definition: typeinfo.h:95
VIEW.
Definition: view.h:61
SEARCH_RESULT
Definition: base_struct.h:51
int GetThermalWidth() const
Definition: class_module.h:250
EDGE_MODULE class definition.
void ClearEditFlags()
Definition: base_struct.h:251
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
INCLUDE_NPTH_T
Definition: class_module.h:53
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetThermalGap() const
Definition: class_module.h:253
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
KIID m_Link
Definition: class_module.h:704
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193
int m_Attributs
Definition: class_module.h:687
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible() Returns information about visibility of a particular layer.
Definition: view.h:416
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)