KiCad PCB EDA Suite
gen_modules_placefile.cpp
Go to the documentation of this file.
1 
4 /*
5  * This program source code file is part of KiCad, a free EDA CAD application.
6  *
7  * Copyright (C) 2015-2016 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 /*
28  * 1 - create ascii files for automatic placement of smd components
29  * 2 - create a module report (pos and module descr) (ascii file)
30  */
31 
32 #include <fctsys.h>
33 #include <confirm.h>
34 #include <kicad_string.h>
35 #include <gestfich.h>
36 #include <wxPcbStruct.h>
37 #include <pgm_base.h>
38 #include <build_version.h>
39 #include <macros.h>
40 #include <reporter.h>
41 
42 #include <class_board.h>
43 #include <class_module.h>
44 
45 #include <pcbnew.h>
47 #include <kiface_i.h>
48 #include <wx_html_report_panel.h>
49 
50 
52 /*
53  * The ASCII format of the kicad place file is:
54  * ### Module positions - created on 04/12/2012 15:24:24 ###
55  * ### Printed by Pcbnew version pcbnew (2012-11-30 BZR 3828)-testing
56  * ## Unit = inches, Angle = deg.
57  * or
58  * ## Unit = mm, Angle = deg.
59  * ## Side : top
60  * or
61  * ## Side : bottom
62  * or
63  * ## Side : all
64  * # Ref Val Package PosX PosY Rot Side
65  * C123 0,1uF/50V SM0603 1.6024 -2.6280 180.0 Front
66  * C124 0,1uF/50V SM0603 1.6063 -2.7579 180.0 Front
67  * C125 0,1uF/50V SM0603 1.6010 -2.8310 180.0 Front
68  * ## End
69  */
70 
71 #define PLACEFILE_UNITS_KEY wxT( "PlaceFileUnits" )
72 #define PLACEFILE_OPT_KEY wxT( "PlaceFileOpts" )
73 #define PLACEFILE_FORMAT_KEY wxT( "PlaceFileFormat" )
74 
75 
76 #define PCB_BACK_SIDE 0
77 #define PCB_FRONT_SIDE 1
78 #define PCB_BOTH_SIDES 2
79 
80 class LIST_MOD // An helper class used to build a list of useful footprints.
81 {
82 public:
83  MODULE* m_Module; // Link to the actual footprint
84  wxString m_Reference; // Its schematic reference
85  wxString m_Value; // Its schematic value
86  LAYER_NUM m_Layer; // its side (B_Cu, or F_Cu)
87 };
88 
89 
95 {
96 public:
99  m_parent( aParent ),
100  m_plotOpts( aParent->GetPlotSettings() )
101  {
103  initDialog();
104 
105  GetSizer()->SetSizeHints(this);
106  Centre();
107  }
108 
109 private:
112  wxConfigBase* m_config;
114 
115  static int m_unitsOpt;
116  static int m_fileOpt;
117  static int m_fileFormat;
118 
119  void initDialog();
120  void OnOutputDirectoryBrowseClicked( wxCommandEvent& event ) override;
121  void OnOKButton( wxCommandEvent& event ) override;
122 
123  bool CreateFiles();
124 
125  // accessors to options:
127  {
128  return m_outputDirectoryName->GetValue();
129  }
130 
131  bool UnitsMM()
132  {
133  return m_radioBoxUnits->GetSelection() == 1;
134  }
135 
136  bool OneFileOnly()
137  {
138  return m_radioBoxFilesCount->GetSelection() == 1;
139  }
140 
141  bool ForceAllSmd()
142  {
143  return m_radioBoxForceSmd->GetSelection() == 1;
144  }
145 };
146 
147 
148 // Static members to remember choices
152 
153 // Use standard board side name. do not translate them,
154 // they are keywords in place file
155 const wxString frontSideName = wxT( "top" );
156 const wxString backSideName = wxT( "bottom" );
157 
159 {
162  m_config->Read( PLACEFILE_OPT_KEY, &m_fileOpt, 0 );
164 
165  // Output directory
167  m_radioBoxUnits->SetSelection( m_unitsOpt );
168  m_radioBoxFilesCount->SetSelection( m_fileOpt );
169  m_rbFormat->SetSelection( m_fileFormat );
170 
171  m_sdbSizerButtonsOK->SetDefault();
172 }
173 
175 {
176  // Build the absolute path of current output plot directory
177  // to preselect it when opening the dialog.
178  wxString path = Prj().AbsolutePath( m_outputDirectoryName->GetValue() );
179 
180  wxDirDialog dirDialog( this, _( "Select Output Directory" ), path );
181 
182  if( dirDialog.ShowModal() == wxID_CANCEL )
183  return;
184 
185  wxFileName dirName = wxFileName::DirName( dirDialog.GetPath() );
186 
187  wxMessageDialog dialog( this, _( "Use a relative path?"),
188  _( "Plot Output Directory" ),
189  wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT );
190 
191  if( dialog.ShowModal() == wxID_YES )
192  {
193  wxString boardFilePath = ( (wxFileName) m_parent->GetBoard()->GetFileName()).GetPath();
194 
195  if( !dirName.MakeRelativeTo( boardFilePath ) )
196  wxMessageBox( _( "Cannot make path relative (target volume different from board file volume)!" ),
197  _( "Plot Output Directory" ), wxOK | wxICON_ERROR );
198  }
199 
200  m_outputDirectoryName->SetValue( dirName.GetFullPath() );
201 }
202 
203 void DIALOG_GEN_MODULE_POSITION::OnOKButton( wxCommandEvent& event )
204 {
205  m_unitsOpt = m_radioBoxUnits->GetSelection();
206  m_fileOpt = m_radioBoxFilesCount->GetSelection();
207  m_fileFormat = m_rbFormat->GetSelection();
208 
209 
213 
214  // Set output directory and replace backslashes with forward ones
215  // (Keep unix convention in cfg files)
216  wxString dirStr;
217  dirStr = m_outputDirectoryName->GetValue();
218  dirStr.Replace( wxT( "\\" ), wxT( "/" ) );
219 
220  m_plotOpts.SetOutputDirectory( dirStr );
222 
223  CreateFiles();
224 
225  // the dialog is not closed here.
226 }
227 
228 
230 {
231  BOARD * brd = m_parent->GetBoard();
232  wxFileName fn;
233  wxString msg;
234  bool singleFile = OneFileOnly();
235  bool useCSVfmt = m_fileFormat == 1;
236  int fullcount = 0;
237 
238  // Count the footprints to place, do not yet create a file
239  int fpcount = m_parent->DoGenFootprintsPositionFile( wxEmptyString, UnitsMM(),
241  useCSVfmt );
242  if( fpcount == 0)
243  {
244  wxMessageBox( _( "No footprint for automated placement." ) );
245  return false;
246  }
247 
248  // Create output directory if it does not exist (also transform it in
249  // absolute path). Bail if it fails
250  wxFileName outputDir = wxFileName::DirName( m_plotOpts.GetOutputDirectory() );
251  wxString boardFilename = m_parent->GetBoard()->GetFileName();
252 
254 
255  if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) )
256  {
257  msg.Printf( _( "Could not write plot files to folder \"%s\"." ),
258  GetChars( outputDir.GetPath() ) );
259  DisplayError( this, msg );
260  return false;
261  }
262 
263  fn = m_parent->GetBoard()->GetFileName();
264  fn.SetPath( outputDir.GetPath() );
265 
266  // Create the the Front or Top side placement file,
267  // or the single file
268  int side = PCB_FRONT_SIDE;
269 
270  if( singleFile )
271  {
272  side = PCB_BOTH_SIDES;
273  fn.SetName( fn.GetName() + wxT( "-" ) + wxT("all") );
274  }
275  else
276  fn.SetName( fn.GetName() + wxT( "-" ) + frontSideName );
277 
278 
279  if( useCSVfmt )
280  {
281  fn.SetName( fn.GetName() + wxT( "-" ) + FootprintPlaceFileExtension );
282  fn.SetExt( wxT( "csv" ) );
283  }
284  else
285  fn.SetExt( FootprintPlaceFileExtension );
286 
287  fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(),
288  ForceAllSmd(), side, useCSVfmt );
289  if( fpcount < 0 )
290  {
291  msg.Printf( _( "Unable to create '%s'." ), GetChars( fn.GetFullPath() ) );
292  wxMessageBox( msg );
294  return false;
295  }
296 
297  if( singleFile )
298  msg.Printf( _( "Place file: '%s'." ), GetChars( fn.GetFullPath() ) );
299  else
300  msg.Printf( _( "Front side (top side) place file: '%s'." ),
301  GetChars( fn.GetFullPath() ) );
303 
304  msg.Printf( _( "Component count: %d." ), fpcount );
306 
307  if( singleFile )
308  {
309  m_reporter->Report( _( "Component Placement File generation OK." ), REPORTER::RPT_ACTION );
310  return true;
311  }
312 
313  // Create the Back or Bottom side placement file
314  fullcount = fpcount;
315  side = PCB_BACK_SIDE;
316  fn = brd->GetFileName();
317  fn.SetPath( outputDir.GetPath() );
318  fn.SetName( fn.GetName() + wxT( "-" ) + backSideName );
319 
320  if( useCSVfmt )
321  {
322  fn.SetName( fn.GetName() + wxT( "-" ) + FootprintPlaceFileExtension );
323  fn.SetExt( wxT( "csv" ) );
324  }
325  else
326  fn.SetExt( FootprintPlaceFileExtension );
327 
328  fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(),
329  ForceAllSmd(), side, useCSVfmt );
330 
331  if( fpcount < 0 )
332  {
333  msg.Printf( _( "Unable to create file '%s'." ), GetChars( fn.GetFullPath() ) );
335  wxMessageBox( msg );
336  return false;
337  }
338 
339  // Display results
340  if( !singleFile )
341  {
342  msg.Printf( _( "Back side (bottom side) place file: '%s'." ), GetChars( fn.GetFullPath() ) );
344 
345  msg.Printf( _( "Component count: %d." ), fpcount );
346 
348  }
349 
350  if( !singleFile )
351  {
352  fullcount += fpcount;
353  msg.Printf( _( "Full component count: %d\n" ), fullcount );
355  }
356 
357  m_reporter->Report( _( "Component Placement File generation OK." ), REPORTER::RPT_ACTION );
358 
359  return true;
360 }
361 
362 // Defined values to write coordinates using inches or mm:
363 static const double conv_unit_inch = 0.001 / IU_PER_MILS ; // units = INCHES
364 static const char unit_text_inch[] = "## Unit = inches, Angle = deg.\n";
365 
366 static const double conv_unit_mm = 1.0 / IU_PER_MM; // units = mm
367 static const char unit_text_mm[] = "## Unit = mm, Angle = deg.\n";
368 
369 static wxPoint File_Place_Offset; // Offset coordinates for generated file.
370 
371 
372 // Sort function use by GenereModulesPosition()
373 // sort is made by side (layer) top layer first
374 // then by reference increasing order
375 static bool sortFPlist( const LIST_MOD& ref, const LIST_MOD& tst )
376 {
377  if( ref.m_Layer == tst.m_Layer )
378  return StrNumCmp( ref.m_Reference, tst.m_Reference, 16 ) < 0;
379 
380  return ref.m_Layer > tst.m_Layer;
381 }
382 
383 
389 static bool HasNonSMDPins( MODULE* aModule )
390 {
391  D_PAD* pad;
392 
393  for( pad = aModule->PadsList(); pad; pad = pad->Next() )
394  {
395  if( pad->GetAttribute() != PAD_ATTRIB_SMD )
396  return true;
397  }
398 
399  return false;
400 }
401 
402 void PCB_EDIT_FRAME::GenFootprintsPositionFile( wxCommandEvent& event )
403 {
404  DIALOG_GEN_MODULE_POSITION dlg( this );
405  dlg.ShowModal();
406 }
407 
408 /*
409  * Creates a footprint position file
410  * aSide = 0 -> Back (bottom) side)
411  * aSide = 1 -> Front (top) side)
412  * aSide = 2 -> both sides
413  * if aFullFileName is empty, the file is not created, only the
414  * count of footprints to place is returned
415  */
416 int PCB_EDIT_FRAME::DoGenFootprintsPositionFile( const wxString& aFullFileName,
417  bool aUnitsMM,
418  bool aForceSmdItems, int aSide,
419  bool aFormatCSV )
420 {
421  MODULE* footprint;
422 
423  // Minimal text lengths:
424  int lenRefText = 8;
425  int lenValText = 8;
426  int lenPkgText = 16;
427 
428  File_Place_Offset = GetAuxOrigin();
429 
430  // Calculating the number of useful footprints (CMS attribute, not VIRTUAL)
431  int footprintCount = 0;
432 
433  // Select units:
434  double conv_unit = aUnitsMM ? conv_unit_mm : conv_unit_inch;
435  const char *unit_text = aUnitsMM ? unit_text_mm : unit_text_inch;
436 
437  // Build and sort the list of footprints alphabetically
438  std::vector<LIST_MOD> list;
439  list.reserve( footprintCount );
440 
441  for( footprint = GetBoard()->m_Modules; footprint; footprint = footprint->Next() )
442  {
443  if( aSide != PCB_BOTH_SIDES )
444  {
445  if( footprint->GetLayer() == B_Cu && aSide == PCB_FRONT_SIDE)
446  continue;
447  if( footprint->GetLayer() == F_Cu && aSide == PCB_BACK_SIDE)
448  continue;
449  }
450 
451  if( footprint->GetAttributes() & MOD_VIRTUAL )
452  {
453  DBG( printf( "skipping footprint %s because it's virtual\n",
454  TO_UTF8( footprint->GetReference() ) );)
455  continue;
456  }
457 
458  if( ( footprint->GetAttributes() & MOD_CMS ) == 0 )
459  {
460  if( aForceSmdItems ) // true to fix a bunch of mis-labeled footprints:
461  {
462  if( !HasNonSMDPins( footprint ) )
463  {
464  // all footprint's pins are SMD, mark the part for pick and place
465  footprint->SetAttributes( footprint->GetAttributes() | MOD_CMS );
466  OnModify();
467  }
468  else
469  {
470  DBG(printf( "skipping %s because its attribute is not CMS and it has non SMD pins\n",
471  TO_UTF8(footprint->GetReference()) ) );
472  continue;
473  }
474  }
475  else
476  continue;
477  }
478 
479  footprintCount++;
480 
481  LIST_MOD item;
482  item.m_Module = footprint;
483  item.m_Reference = footprint->GetReference();
484  item.m_Value = footprint->GetValue();
485  item.m_Layer = footprint->GetLayer();
486  list.push_back( item );
487 
488  lenRefText = std::max( lenRefText, int(item.m_Reference.length()) );
489  lenValText = std::max( lenValText, int(item.m_Value.length()) );
490  lenPkgText = std::max( lenPkgText, int(item.m_Module->GetFPID().GetLibItemName().length()) );
491  }
492 
493  if( aFullFileName.IsEmpty() )
494  return footprintCount;
495 
496  FILE * file = wxFopen( aFullFileName, wxT( "wt" ) );
497  if( file == NULL )
498  return -1;
499 
500  if( list.size() > 1 )
501  sort( list.begin(), list.end(), sortFPlist );
502 
503  // Switch the locale to standard C (needed to print floating point numbers)
504  LOCALE_IO toggle;
505 
506  if( aFormatCSV )
507  {
508  wxChar csv_sep = ',';
509 
510  // Set first line:;
511  fprintf( file, "Ref%cVal%cPackage%cPosX%cPosY%cRot%cSide\n",
512  csv_sep, csv_sep, csv_sep, csv_sep, csv_sep, csv_sep );
513 
514  for( int ii = 0; ii < footprintCount; ii++ )
515  {
516  wxPoint footprint_pos;
517  footprint_pos = list[ii].m_Module->GetPosition();
518  footprint_pos -= File_Place_Offset;
519 
520  LAYER_NUM layer = list[ii].m_Module->GetLayer();
521  wxASSERT( layer == F_Cu || layer == B_Cu );
522 
523  wxString line = list[ii].m_Reference;
524  line << csv_sep;
525  line << list[ii].m_Value;
526  line << csv_sep;
527  line << list[ii].m_Module->GetFPID().GetLibItemName().wx_str();
528  line << csv_sep;
529 
530  line << wxString::Format( "%f%c%f%c%f",
531  footprint_pos.x * conv_unit, csv_sep,
532  // Keep the Y axis oriented from bottom to top,
533  // ( change y coordinate sign )
534  -footprint_pos.y * conv_unit, csv_sep,
535  list[ii].m_Module->GetOrientation() / 10.0 );
536  line << csv_sep;
537 
538  line << ( (layer == F_Cu ) ? frontSideName : backSideName );
539  line << '\n';
540 
541  fputs( TO_UTF8( line ), file );
542  }
543  }
544  else
545  {
546  // Write file header
547  fprintf( file, "### Module positions - created on %s ###\n", TO_UTF8( DateAndTime() ) );
548 
549  wxString Title = Pgm().App().GetAppName() + wxT( " " ) + GetBuildVersion();
550  fprintf( file, "### Printed by Pcbnew version %s\n", TO_UTF8( Title ) );
551 
552  fputs( unit_text, file );
553 
554  fputs( "## Side : ", file );
555 
556  if( aSide == PCB_BACK_SIDE )
557  fputs( TO_UTF8( backSideName ), file );
558  else if( aSide == PCB_FRONT_SIDE )
559  fputs( TO_UTF8( frontSideName ), file );
560  else
561  fputs( "All", file );
562 
563  fputs( "\n", file );
564 
565  fprintf(file, "%-*s %-*s %-*s %9.9s %9.9s %8.8s %s\n",
566  int(lenRefText), "# Ref",
567  int(lenValText), "Val",
568  int(lenPkgText), "Package",
569  "PosX", "PosY", "Rot", "Side" );
570 
571  for( int ii = 0; ii < footprintCount; ii++ )
572  {
573  wxPoint footprint_pos;
574  footprint_pos = list[ii].m_Module->GetPosition();
575  footprint_pos -= File_Place_Offset;
576 
577  LAYER_NUM layer = list[ii].m_Module->GetLayer();
578  wxASSERT( layer == F_Cu || layer == B_Cu );
579 
580  const wxString& ref = list[ii].m_Reference;
581  const wxString& val = list[ii].m_Value;
582  const wxString& pkg = list[ii].m_Module->GetFPID().GetLibItemName();
583 
584  fprintf(file, "%-*s %-*s %-*s %9.4f %9.4f %8.4f %s\n",
585  lenRefText, TO_UTF8( ref ),
586  lenValText, TO_UTF8( val ),
587  lenPkgText, TO_UTF8( pkg ),
588  footprint_pos.x * conv_unit,
589  // Keep the coordinates in the first quadrant,
590  // (i.e. change y sign
591  -footprint_pos.y * conv_unit,
592  list[ii].m_Module->GetOrientation() / 10.0,
593  (layer == F_Cu ) ? TO_UTF8( frontSideName ) : TO_UTF8( backSideName ));
594  }
595 
596  // Write EOF
597  fputs( "## End\n", file );
598  }
599 
600  fclose( file );
601  return footprintCount;
602 }
603 
604 
605 void PCB_EDIT_FRAME::GenFootprintsReport( wxCommandEvent& event )
606 {
607  wxFileName fn;
608 
609  wxString boardFilePath = ( (wxFileName) GetBoard()->GetFileName()).GetPath();
610  wxDirDialog dirDialog( this, _( "Select Output Directory" ), boardFilePath );
611 
612  if( dirDialog.ShowModal() == wxID_CANCEL )
613  return;
614 
615  fn = GetBoard()->GetFileName();
616  fn.SetPath( dirDialog.GetPath() );
617  fn.SetExt( wxT( "rpt" ) );
618 
619  bool unitMM = g_UserUnit != INCHES;
620  bool success = DoGenFootprintsReport( fn.GetFullPath(), unitMM );
621 
622  wxString msg;
623  if( success )
624  {
625  msg.Printf( _( "Footprint report file created:\n'%s'" ),
626  GetChars( fn.GetFullPath() ) );
627  wxMessageBox( msg, _( "Footprint Report" ), wxICON_INFORMATION );
628  }
629 
630  else
631  {
632  msg.Printf( _( "Unable to create '%s'" ), GetChars( fn.GetFullPath() ) );
633  DisplayError( this, msg );
634  }
635 }
636 
637 /* Print a module report.
638  */
639 bool PCB_EDIT_FRAME::DoGenFootprintsReport( const wxString& aFullFilename, bool aUnitsMM )
640 {
641  wxString msg;
642  FILE* rptfile;
643  wxPoint module_pos;
644 
645  File_Place_Offset = wxPoint( 0, 0 );
646 
647  rptfile = wxFopen( aFullFilename, wxT( "wt" ) );
648 
649  if( rptfile == NULL )
650  return false;
651 
652  // Select units:
653  double conv_unit = aUnitsMM ? conv_unit_mm : conv_unit_inch;
654  const char *unit_text = aUnitsMM ? unit_text_mm : unit_text_inch;
655 
656  LOCALE_IO toggle;
657 
658  // Generate header file comments.)
659  fprintf( rptfile, "## Footprint report - date %s\n", TO_UTF8( DateAndTime() ) );
660 
661  wxString Title = Pgm().App().GetAppName() + wxT( " " ) + GetBuildVersion();
662  fprintf( rptfile, "## Created by Pcbnew version %s\n", TO_UTF8( Title ) );
663  fputs( unit_text, rptfile );
664 
665  fputs( "\n$BeginDESCRIPTION\n", rptfile );
666 
667  EDA_RECT bbbox = GetBoard()->ComputeBoundingBox();
668 
669  fputs( "\n$BOARD\n", rptfile );
670 
671  fprintf( rptfile, "upper_left_corner %9.6f %9.6f\n",
672  bbbox.GetX() * conv_unit,
673  bbbox.GetY() * conv_unit );
674 
675  fprintf( rptfile, "lower_right_corner %9.6f %9.6f\n",
676  bbbox.GetRight() * conv_unit,
677  bbbox.GetBottom() * conv_unit );
678 
679  fputs( "$EndBOARD\n\n", rptfile );
680 
681  for( MODULE* Module = GetBoard()->m_Modules; Module; Module = Module->Next() )
682  {
683  fprintf( rptfile, "$MODULE %s\n", EscapedUTF8( Module->GetReference() ).c_str() );
684 
685  fprintf( rptfile, "reference %s\n", EscapedUTF8( Module->GetReference() ).c_str() );
686  fprintf( rptfile, "value %s\n", EscapedUTF8( Module->GetValue() ).c_str() );
687  fprintf( rptfile, "footprint %s\n",
688  EscapedUTF8( FROM_UTF8( Module->GetFPID().Format().c_str() ) ).c_str() );
689 
690  msg = wxT( "attribut" );
691 
692  if( Module->GetAttributes() & MOD_VIRTUAL )
693  msg += wxT( " virtual" );
694 
695  if( Module->GetAttributes() & MOD_CMS )
696  msg += wxT( " smd" );
697 
698  if( ( Module->GetAttributes() & (MOD_VIRTUAL | MOD_CMS) ) == 0 )
699  msg += wxT( " none" );
700 
701  msg += wxT( "\n" );
702  fputs( TO_UTF8( msg ), rptfile );
703 
704  module_pos = Module->GetPosition();
705  module_pos.x -= File_Place_Offset.x;
706  module_pos.y -= File_Place_Offset.y;
707 
708  fprintf( rptfile, "position %9.6f %9.6f orientation %.2f\n",
709  module_pos.x * conv_unit,
710  module_pos.y * conv_unit,
711  Module->GetOrientation() / 10.0 );
712 
713  if( Module->GetLayer() == F_Cu )
714  fputs( "layer front\n", rptfile );
715  else if( Module->GetLayer() == B_Cu )
716  fputs( "layer back\n", rptfile );
717  else
718  fputs( "layer other\n", rptfile );
719 
720  for( D_PAD* pad = Module->PadsList(); pad != NULL; pad = pad->Next() )
721  {
722  fprintf( rptfile, "$PAD \"%s\"\n", TO_UTF8( pad->GetName() ) );
723  int layer = 0;
724 
725  if( pad->GetLayerSet()[B_Cu] )
726  layer = 1;
727 
728  if( pad->GetLayerSet()[F_Cu] )
729  layer |= 2;
730 
731  static const char* layer_name[4] = { "nocopper", "back", "front", "both" };
732  fprintf( rptfile, "Shape %s Layer %s\n", TO_UTF8( pad->ShowPadShape() ), layer_name[layer] );
733 
734  fprintf( rptfile, "position %9.6f %9.6f size %9.6f %9.6f orientation %.2f\n",
735  pad->GetPos0().x * conv_unit, pad->GetPos0().y * conv_unit,
736  pad->GetSize().x * conv_unit, pad->GetSize().y * conv_unit,
737  (pad->GetOrientation() - Module->GetOrientation()) / 10.0 );
738 
739  fprintf( rptfile, "drill %9.6f\n", pad->GetDrillSize().x * conv_unit );
740 
741  fprintf( rptfile, "shape_offset %9.6f %9.6f\n",
742  pad->GetOffset().x * conv_unit,
743  pad->GetOffset().y * conv_unit );
744 
745  fprintf( rptfile, "$EndPAD\n" );
746  }
747 
748  fprintf( rptfile, "$EndMODULE %s\n\n", TO_UTF8 (Module->GetReference() ) );
749  }
750 
751  // Generate EOF.
752  fputs( "$EndDESCRIPTION\n", rptfile );
753  fclose( rptfile );
754 
755  return true;
756 }
virtual void OnModify() override
Function OnModify must be called after a board change to set the modified flag.
Definition: pcbframe.cpp:994
void OnOutputDirectoryBrowseClicked(wxCommandEvent &event) override
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:398
This file is part of the common library TODO brief description.
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:166
static bool HasNonSMDPins(MODULE *aModule)
Helper function HasNonSMDPins returns true if the given module has any non smd pins, such as through hole and therefore cannot be placed automatically.
This file is part of the common library.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
EDA_RECT ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Function ComputeBoundingBox calculates the bounding box containing all board items (or board edge seg...
const wxString FootprintPlaceFileExtension
Class BOARD to handle a board.
const wxString frontSideName
MODULE * Next() const
Definition: class_module.h:120
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:61
VTBL_ENTRY wxApp & App()
Function App returns a bare naked wxApp, which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition: pgm_base.cpp:323
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:76
BOARD * GetBoard() const
const wxString & GetValue() const
Function GetValue.
Definition: class_module.h:467
static wxPoint File_Place_Offset
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: kicad.cpp:65
Class REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:61
The dialog to create footprint position files, and choose options (one or 2 files, units and force all SMD footprints in list)
Class DIALOG_GEN_MODULE_POSITION_BASE.
const wxPoint & GetAuxOrigin() const override
Function GetAuxOrigin returns the origin of the axis used for plotting and various exports...
static bool sortFPlist(const LIST_MOD &ref, const LIST_MOD &tst)
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
This file contains miscellaneous commonly used macros and functions.
static const double conv_unit_inch
BOARD_ITEM * Next() const
const LIB_ID & GetFPID() const
Definition: class_module.h:184
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
int DoGenFootprintsPositionFile(const wxString &aFullFileName, bool aUnitsMM, bool aForceSmdItems, int aSide, bool aFormatCSV=false)
Function DoGenFootprintsPositionFile Creates an ascii footprint position file.
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
std::string EscapedUTF8(const wxString &aString)
Function EscapedUTF8 returns an 8 bit UTF8 string given aString in unicode form.
Definition: string.cpp:137
bool DoGenFootprintsReport(const wxString &aFullFilename, bool aUnitsMM)
Function DoGenFootprintsReport Creates an ascii footprint report file giving some infos on footprints...
wxString GetOutputDirectory() const
void GenFootprintsReport(wxCommandEvent &event)
Function GenFootprintsReport Calls DoGenFootprintsReport to create a footprint reprot file See DoGenF...
#define PCB_FRONT_SIDE
wxString GetBuildVersion()
Function GetBuildVersion Return the build version string.
const wxString & GetFileName() const
Definition: class_board.h:234
const UTF8 & GetLibItemName() const
Definition: lib_id.h:115
Definition: common.h:145
bool EnsureFileDirectoryExists(wxFileName *aTargetFullFileName, const wxString &aBaseFilename, REPORTER *aReporter)
Helper function EnsureFileDirectoryExists make aTargetFullFileName absolute and creates the path of t...
Definition: common.cpp:267
REPORTER & Reporter()
returns the reporter object that reports to this panel
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:382
D_PAD * Next() const
Definition: class_pad.h:160
The common library.
int GetAttributes() const
Definition: class_module.h:217
wxConfigBase * KifaceSettings() const
Definition: kiface_i.h:103
static const char unit_text_mm[]
virtual void SetPlotSettings(const PCB_PLOT_PARAMS &aSettings)
static const char unit_text_inch[]
std::string::size_type length() const
Definition: utf8.h:114
#define PCB_BOTH_SIDES
int GetBottom() const
DIALOG_GEN_MODULE_POSITION(PCB_EDIT_FRAME *aParent)
#define PLACEFILE_UNITS_KEY
void SetOutputDirectory(wxString aDir)
int GetRight() const
const wxString backSideName
Class PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board...
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
#define PCB_BACK_SIDE
void OnOKButton(wxCommandEvent &event) override
#define PLACEFILE_FORMAT_KEY
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:92
see class PGM_BASE
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
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:439
Virtual component: when created by copper shapes on board (Like edge card connectors, mounting hole...)
Definition: class_module.h:78
Class EDA_RECT handles the component boundary box.
int GetX() const
static const double conv_unit_mm
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
int GetY() const
#define PLACEFILE_OPT_KEY
#define DBG(x)
Definition: fctsys.h:33
DLIST< D_PAD > & PadsList()
Definition: class_module.h:154
Module description (excepted pads)
int StrNumCmp(const wxString &aString1, const wxString &aString2, int aLength, bool aIgnoreCase)
Function StrLenNumCmp is a routine compatible with qsort() to sort by alphabetical order...
Definition: string.cpp:238
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:73
wxString DateAndTime()
Function DateAndTime.
Definition: string.cpp:229
void SetAttributes(int aAttributes)
Definition: class_module.h:218
void GenFootprintsPositionFile(wxCommandEvent &event)
Function GenFootprintsPositionFile Calls DoGenFootprintsPositionFile to create a footprint position f...