KiCad PCB EDA Suite
export_idf.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2013 Cirilo Bernardo
9  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28 
29 
30 #include <list>
31 #include <locale_io.h>
32 #include <macros.h>
33 #include <pcb_edit_frame.h>
34 #include <board.h>
35 #include <board_design_settings.h>
36 #include <footprint.h>
37 #include <fp_shape.h>
38 #include <idf_parser.h>
39 #include <pad.h>
40 #include <build_version.h>
41 #include <wx/msgdlg.h>
42 #include "project.h"
43 #include "kiway.h"
44 #include "3d_cache/3d_cache.h"
45 #include "filename_resolver.h"
46 
47 #ifndef PCBNEW
48 #define PCBNEW // needed to define the right value of Millimeter2iu(x)
49 #endif
50 #include <convert_to_biu.h> // to define Millimeter2iu(x)
51 
52 
53 // assumed default graphical line thickness: == 0.1mm
54 #define LINE_WIDTH (Millimeter2iu( 0.1 ))
55 
56 
58 
59 
64 static void idf_export_outline( BOARD* aPcb, IDF3_BOARD& aIDFBoard )
65 {
66  double scale = aIDFBoard.GetUserScale();
67 
68  PCB_SHAPE* graphic; // KiCad graphical item
69  IDF_POINT sp, ep; // start and end points from KiCad item
70 
71  std::list< IDF_SEGMENT* > lines; // IDF intermediate form of KiCad graphical item
72  IDF_OUTLINE* outline = nullptr; // graphical items forming an outline or cutout
73 
74  // NOTE: IMPLEMENTATION
75  // If/when component cutouts are allowed, we must implement them separately. Cutouts
76  // must be added to the board outline section and not to the Other Outline section.
77  // The footprint cutouts should be handled via the idf_export_footprint() routine.
78 
79  double offX, offY;
80  aIDFBoard.GetUserOffset( offX, offY );
81 
82  // Retrieve segments and arcs from the board
83  for( BOARD_ITEM* item : aPcb->Drawings() )
84  {
85  if( item->Type() != PCB_SHAPE_T || item->GetLayer() != Edge_Cuts )
86  continue;
87 
88  graphic = (PCB_SHAPE*) item;
89 
90  switch( graphic->GetShape() )
91  {
92  case SHAPE_T::SEGMENT:
93  {
94  if( ( graphic->GetStart().x == graphic->GetEnd().x )
95  && ( graphic->GetStart().y == graphic->GetEnd().y ) )
96  {
97  break;
98  }
99 
100  sp.x = graphic->GetStart().x * scale + offX;
101  sp.y = -graphic->GetStart().y * scale + offY;
102  ep.x = graphic->GetEnd().x * scale + offX;
103  ep.y = -graphic->GetEnd().y * scale + offY;
104  IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep );
105 
106  if( seg )
107  lines.push_back( seg );
108 
109  break;
110  }
111 
112  case SHAPE_T::RECT:
113  {
114  if( ( graphic->GetStart().x == graphic->GetEnd().x )
115  && ( graphic->GetStart().y == graphic->GetEnd().y ) )
116  {
117  break;
118  }
119 
120  double top = graphic->GetStart().y * scale + offY;
121  double left = graphic->GetStart().x * scale + offX;
122  double bottom = graphic->GetEnd().y * scale + offY;
123  double right = graphic->GetEnd().x * scale + offX;
124 
125  IDF_POINT corners[4];
126  corners[0] = IDF_POINT( left, top );
127  corners[1] = IDF_POINT( right, top );
128  corners[2] = IDF_POINT( right, bottom );
129  corners[3] = IDF_POINT( left, bottom );
130 
131  lines.push_back( new IDF_SEGMENT( corners[0], corners[1] ) );
132  lines.push_back( new IDF_SEGMENT( corners[1], corners[2] ) );
133  lines.push_back( new IDF_SEGMENT( corners[2], corners[3] ) );
134  lines.push_back( new IDF_SEGMENT( corners[3], corners[0] ) );
135  break;
136  }
137 
138  case SHAPE_T::ARC:
139  {
140  if( ( graphic->GetCenter().x == graphic->GetArcStart().x )
141  && ( graphic->GetCenter().y == graphic->GetArcStart().y ) )
142  {
143  break;
144  }
145 
146  sp.x = graphic->GetCenter().x * scale + offX;
147  sp.y = -graphic->GetCenter().y * scale + offY;
148  ep.x = graphic->GetArcStart().x * scale + offX;
149  ep.y = -graphic->GetArcStart().y * scale + offY;
150  IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep, -graphic->GetAngle() / 10.0, true );
151 
152  if( seg )
153  lines.push_back( seg );
154 
155  break;
156  }
157 
158  case SHAPE_T::CIRCLE:
159  {
160  if( graphic->GetRadius() == 0 )
161  break;
162 
163  sp.x = graphic->GetCenter().x * scale + offX;
164  sp.y = -graphic->GetCenter().y * scale + offY;
165  ep.x = sp.x - graphic->GetRadius() * scale;
166  ep.y = sp.y;
167 
168  // Circles must always have an angle of +360 deg. to appease
169  // quirky MCAD implementations of IDF.
170  IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep, 360.0, true );
171 
172  if( seg )
173  lines.push_back( seg );
174 
175  break;
176  }
177 
178  default:
179  break;
180  }
181  }
182 
183  // if there is no outline then use the bounding box
184  if( lines.empty() )
185  {
186  goto UseBoundingBox;
187  }
188 
189  // get the board outline and write it out
190  // note: we do not use a try/catch block here since we intend
191  // to simply ignore unclosed loops and continue processing
192  // until we're out of segments to process
193  outline = new IDF_OUTLINE;
194  IDF3::GetOutline( lines, *outline );
195 
196  if( outline->empty() )
197  goto UseBoundingBox;
198 
199  aIDFBoard.AddBoardOutline( outline );
200  outline = nullptr;
201 
202  // get all cutouts and write them out
203  while( !lines.empty() )
204  {
205  if( !outline )
206  outline = new IDF_OUTLINE;
207 
208  IDF3::GetOutline( lines, *outline );
209 
210  if( outline->empty() )
211  {
212  outline->Clear();
213  continue;
214  }
215 
216  aIDFBoard.AddBoardOutline( outline );
217  outline = nullptr;
218  }
219 
220  return;
221 
222 UseBoundingBox:
223 
224  // clean up if necessary
225  while( !lines.empty() )
226  {
227  delete lines.front();
228  lines.pop_front();
229  }
230 
231  if( outline )
232  outline->Clear();
233  else
234  outline = new IDF_OUTLINE;
235 
236  // Fetch a rectangular bounding box for the board; there is always some uncertainty in the
237  // board dimensions computed via ComputeBoundingBox() since this depends on the individual
238  // footprint entities.
239  EDA_RECT bbbox = aPcb->GetBoardEdgesBoundingBox();
240 
241  // convert to mm and compensate for an assumed LINE_WIDTH line thickness
242  double x = ( bbbox.GetOrigin().x + LINE_WIDTH / 2 ) * scale + offX;
243  double y = ( bbbox.GetOrigin().y + LINE_WIDTH / 2 ) * scale + offY;
244  double dx = ( bbbox.GetSize().x - LINE_WIDTH ) * scale;
245  double dy = ( bbbox.GetSize().y - LINE_WIDTH ) * scale;
246 
247  double px[4], py[4];
248  px[0] = x;
249  py[0] = y;
250 
251  px[1] = x;
252  py[1] = y + dy;
253 
254  px[2] = x + dx;
255  py[2] = y + dy;
256 
257  px[3] = x + dx;
258  py[3] = y;
259 
260  IDF_POINT p1, p2;
261 
262  p1.x = px[3];
263  p1.y = py[3];
264  p2.x = px[0];
265  p2.y = py[0];
266 
267  outline->push( new IDF_SEGMENT( p1, p2 ) );
268 
269  for( int i = 1; i < 4; ++i )
270  {
271  p1.x = px[i - 1];
272  p1.y = py[i - 1];
273  p2.x = px[i];
274  p2.y = py[i];
275 
276  outline->push( new IDF_SEGMENT( p1, p2 ) );
277  }
278 
279  aIDFBoard.AddBoardOutline( outline );
280 }
281 
282 
288 static void idf_export_footprint( BOARD* aPcb, FOOTPRINT* aFootprint, IDF3_BOARD& aIDFBoard )
289 {
290  // Reference Designator
291  std::string crefdes = TO_UTF8( aFootprint->Reference().GetShownText() );
292 
293  if( crefdes.empty() || !crefdes.compare( "~" ) )
294  {
295  std::string cvalue = TO_UTF8( aFootprint->Value().GetShownText() );
296 
297  // if both the RefDes and Value are empty or set to '~' the board owns the part,
298  // otherwise associated parts of the footprint must be marked NOREFDES.
299  if( cvalue.empty() || !cvalue.compare( "~" ) )
300  crefdes = "BOARD";
301  else
302  crefdes = "NOREFDES";
303  }
304 
305  // TODO: If footprint cutouts are supported we must add code here
306  // for( EDA_ITEM* item = aFootprint->GraphicalItems(); item != NULL; item = item->Next() )
307  // {
308  // if( item->Type() != PCB_FP_SHAPE_T || item->GetLayer() != Edge_Cuts )
309  // continue;
310  // code to export cutouts
311  // }
312 
313  // Export pads
314  double drill, x, y;
315  double scale = aIDFBoard.GetUserScale();
316  IDF3::KEY_PLATING kplate;
317  std::string pintype;
318  std::string tstr;
319 
320  double dx, dy;
321 
322  aIDFBoard.GetUserOffset( dx, dy );
323 
324  for( auto pad : aFootprint->Pads() )
325  {
326  drill = (double) pad->GetDrillSize().x * scale;
327  x = pad->GetPosition().x * scale + dx;
328  y = -pad->GetPosition().y * scale + dy;
329 
330  // Export the hole on the edge layer
331  if( drill > 0.0 )
332  {
333  // plating
334  if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
335  kplate = IDF3::NPTH;
336  else
337  kplate = IDF3::PTH;
338 
339  // hole type
340  tstr = TO_UTF8( pad->GetName() );
341 
342  if( tstr.empty() || !tstr.compare( "0" ) || !tstr.compare( "~" )
343  || ( kplate == IDF3::NPTH )
344  || ( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
345  pintype = "MTG";
346  else
347  pintype = "PIN";
348 
349  // fields:
350  // 1. hole dia. : float
351  // 2. X coord : float
352  // 3. Y coord : float
353  // 4. plating : PTH | NPTH
354  // 5. Assoc. part : BOARD | NOREFDES | PANEL | {"refdes"}
355  // 6. type : PIN | VIA | MTG | TOOL | { "other" }
356  // 7. owner : MCAD | ECAD | UNOWNED
357  if( ( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG )
358  && ( pad->GetDrillSize().x != pad->GetDrillSize().y ) )
359  {
360  // NOTE: IDF does not have direct support for slots;
361  // slots are implemented as a board cutout and we
362  // cannot represent plating or reference designators
363 
364  double dlength = pad->GetDrillSize().y * scale;
365 
366  // NOTE: The orientation of footprints and pads have
367  // the opposite sense due to KiCad drawing on a
368  // screen with a LH coordinate system
369  double angle = pad->GetOrientation() / 10.0;
370 
371  // NOTE: Since this code assumes the scenario where
372  // GetDrillSize().y is the length but idf_parser.cpp
373  // assumes a length along the X axis, the orientation
374  // must be shifted +90 deg when GetDrillSize().y is
375  // the major axis.
376 
377  if( dlength < drill )
378  {
379  std::swap( drill, dlength );
380  }
381  else
382  {
383  angle += 90.0;
384  }
385 
386  // NOTE: KiCad measures a slot's length from end to end
387  // rather than between the centers of the arcs
388  dlength -= drill;
389 
390  aIDFBoard.AddSlot( drill, dlength, angle, x, y );
391  }
392  else
393  {
394  IDF_DRILL_DATA *dp = new IDF_DRILL_DATA( drill, x, y, kplate, crefdes,
395  pintype, IDF3::ECAD );
396 
397  if( !aIDFBoard.AddDrill( dp ) )
398  {
399  delete dp;
400 
401  std::ostringstream ostr;
402  ostr << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__;
403  ostr << "(): could not add drill";
404 
405  throw std::runtime_error( ostr.str() );
406  }
407  }
408  }
409  }
410 
411  // add any valid models to the library item list
412  std::string refdes;
413 
414  IDF3_COMPONENT* comp = nullptr;
415 
416  auto sM = aFootprint->Models().begin();
417  auto eM = aFootprint->Models().end();
418  wxFileName idfFile;
419  wxString idfExt;
420 
421  while( sM != eM )
422  {
423  idfFile.Assign( resolver->ResolvePath( sM->m_Filename ) );
424  idfExt = idfFile.GetExt();
425 
426  if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) )
427  {
428  ++sM;
429  continue;
430  }
431 
432  if( refdes.empty() )
433  {
434  refdes = TO_UTF8( aFootprint->Reference().GetShownText() );
435 
436  // NOREFDES cannot be used or else the software gets confused
437  // when writing out the placement data due to conflicting
438  // placement and layer specifications; to work around this we
439  // create a (hopefully) unique refdes for our exported part.
440  if( refdes.empty() || !refdes.compare( "~" ) )
441  refdes = aIDFBoard.GetNewRefDes();
442  }
443 
444  IDF3_COMP_OUTLINE* outline;
445 
446  outline = aIDFBoard.GetComponentOutline( idfFile.GetFullPath() );
447 
448  if( !outline )
449  throw( std::runtime_error( aIDFBoard.GetError() ) );
450 
451  double rotz = aFootprint->GetOrientation() / 10.0;
452  double locx = sM->m_Offset.x * 25.4; // part offsets are in inches
453  double locy = sM->m_Offset.y * 25.4;
454  double locz = sM->m_Offset.z * 25.4;
455  double lrot = sM->m_Rotation.z;
456 
457  bool top = ( aFootprint->GetLayer() == B_Cu ) ? false : true;
458 
459  if( top )
460  {
461  locy = -locy;
462  RotatePoint( &locx, &locy, aFootprint->GetOrientation() );
463  locy = -locy;
464  }
465 
466  if( !top )
467  {
468  lrot = -lrot;
469  RotatePoint( &locx, &locy, aFootprint->GetOrientation() );
470  locy = -locy;
471 
472  rotz = 180.0 - rotz;
473 
474  if( rotz >= 360.0 )
475  while( rotz >= 360.0 ) rotz -= 360.0;
476 
477  if( rotz <= -360.0 )
478  while( rotz <= -360.0 ) rotz += 360.0;
479  }
480 
481  if( comp == nullptr )
482  comp = aIDFBoard.FindComponent( refdes );
483 
484  if( comp == nullptr )
485  {
486  comp = new IDF3_COMPONENT( &aIDFBoard );
487 
488  if( comp == nullptr )
489  throw( std::runtime_error( aIDFBoard.GetError() ) );
490 
491  comp->SetRefDes( refdes );
492 
493  if( top )
494  {
495  comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
496  -aFootprint->GetPosition().y * scale + dy,
497  rotz, IDF3::LYR_TOP );
498  }
499  else
500  {
501  comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
502  -aFootprint->GetPosition().y * scale + dy,
503  rotz, IDF3::LYR_BOTTOM );
504  }
505 
506  comp->SetPlacement( IDF3::PS_ECAD );
507 
508  aIDFBoard.AddComponent( comp );
509  }
510  else
511  {
512  double refX, refY, refA;
513  IDF3::IDF_LAYER side;
514 
515  if( ! comp->GetPosition( refX, refY, refA, side ) )
516  {
517  // place the item
518  if( top )
519  {
520  comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
521  -aFootprint->GetPosition().y * scale + dy,
522  rotz, IDF3::LYR_TOP );
523  }
524  else
525  {
526  comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
527  -aFootprint->GetPosition().y * scale + dy,
528  rotz, IDF3::LYR_BOTTOM );
529  }
530 
531  comp->SetPlacement( IDF3::PS_ECAD );
532 
533  }
534  else
535  {
536  // check that the retrieved component matches this one
537  refX = refX - ( aFootprint->GetPosition().x * scale + dx );
538  refY = refY - ( -aFootprint->GetPosition().y * scale + dy );
539  refA = refA - rotz;
540  refA *= refA;
541  refX *= refX;
542  refY *= refY;
543  refX += refY;
544 
545  // conditions: same side, X,Y coordinates within 10 microns,
546  // angle within 0.01 degree
547  if( ( top && side == IDF3::LYR_BOTTOM ) || ( !top && side == IDF3::LYR_TOP )
548  || ( refA > 0.0001 ) || ( refX > 0.0001 ) )
549  {
550  comp->GetPosition( refX, refY, refA, side );
551 
552  std::ostringstream ostr;
553  ostr << "* " << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__ << "():\n";
554  ostr << "* conflicting Reference Designator '" << refdes << "'\n";
555  ostr << "* X loc: " << ( aFootprint->GetPosition().x * scale + dx);
556  ostr << " vs. " << refX << "\n";
557  ostr << "* Y loc: " << ( -aFootprint->GetPosition().y * scale + dy);
558  ostr << " vs. " << refY << "\n";
559  ostr << "* angle: " << rotz;
560  ostr << " vs. " << refA << "\n";
561 
562  if( top )
563  ostr << "* TOP vs. ";
564  else
565  ostr << "* BOTTOM vs. ";
566 
567  if( side == IDF3::LYR_TOP )
568  ostr << "TOP";
569  else
570  ostr << "BOTTOM";
571 
572  throw( std::runtime_error( ostr.str() ) );
573  }
574  }
575  }
576 
577  // create the local data ...
578  IDF3_COMP_OUTLINE_DATA* data = new IDF3_COMP_OUTLINE_DATA( comp, outline );
579 
580  data->SetOffsets( locx, locy, locz, lrot );
581  comp->AddOutlineData( data );
582  ++sM;
583  }
584 }
585 
586 
591 bool PCB_EDIT_FRAME::Export_IDF3( BOARD* aPcb, const wxString& aFullFileName,
592  bool aUseThou, double aXRef, double aYRef )
593 {
594  IDF3_BOARD idfBoard( IDF3::CAD_ELEC );
595 
596  // Switch the locale to standard C (needed to print floating point numbers)
597  LOCALE_IO toggle;
598 
599  resolver = Prj().Get3DCacheManager()->GetResolver();
600 
601  bool ok = true;
602  double scale = MM_PER_IU; // we must scale internal units to mm for IDF
603  IDF3::IDF_UNIT idfUnit;
604 
605  if( aUseThou )
606  {
607  idfUnit = IDF3::UNIT_THOU;
608  idfBoard.SetUserPrecision( 1 );
609  }
610  else
611  {
612  idfUnit = IDF3::UNIT_MM;
613  idfBoard.SetUserPrecision( 5 );
614  }
615 
616  wxFileName brdName = aPcb->GetFileName();
617 
618  idfBoard.SetUserScale( scale );
619  idfBoard.SetBoardThickness( aPcb->GetDesignSettings().GetBoardThickness() * scale );
620  idfBoard.SetBoardName( TO_UTF8( brdName.GetFullName() ) );
621  idfBoard.SetBoardVersion( 0 );
622  idfBoard.SetLibraryVersion( 0 );
623 
624  std::ostringstream ostr;
625  ostr << "KiCad " << TO_UTF8( GetBuildVersion() );
626  idfBoard.SetIDFSource( ostr.str() );
627 
628  try
629  {
630  // set up the board reference point
631  idfBoard.SetUserOffset( -aXRef, aYRef );
632 
633  // Export the board outline
634  idf_export_outline( aPcb, idfBoard );
635 
636  // Output the drill holes and footprint (library) data.
637  for( FOOTPRINT* footprint : aPcb->Footprints() )
638  idf_export_footprint( aPcb, footprint, idfBoard );
639 
640  if( !idfBoard.WriteFile( aFullFileName, idfUnit, false ) )
641  {
642  wxString msg;
643  msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( idfBoard.GetError().c_str() );
644  wxMessageBox( msg );
645 
646  ok = false;
647  }
648  }
649  catch( const IO_ERROR& ioe )
650  {
651  wxString msg;
652  msg << _( "IDF Export Failed:\n" ) << ioe.What();
653  wxMessageBox( msg );
654 
655  ok = false;
656  }
657  catch( const std::exception& e )
658  {
659  wxString msg;
660  msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( e.what() );
661  wxMessageBox( msg );
662  ok = false;
663  }
664 
665  return ok;
666 }
Arcs (with rounded ends)
std::list< FP_3DMODEL > & Models()
Definition: footprint.h:173
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: pcb_shape.h:134
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
SHAPE_T GetShape() const
Definition: pcb_shape.h:110
const EDA_RECT GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:742
static void idf_export_outline(BOARD *aPcb, IDF3_BOARD &aIDFBoard)
Retrieve line segment information from the edge layer and compiles the data into a form which can be ...
Definition: export_idf.cpp:64
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:487
usual segment : line with rounded ends
bool Export_IDF3(BOARD *aPcb, const wxString &aFullFileName, bool aUseThou, double aXRef, double aYRef)
Create an IDF3 compliant BOARD (*.emn) and LIBRARY (*.emp) file.
Definition: export_idf.cpp:591
double GetOrientation() const
Definition: footprint.h:181
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
const wxString & GetFileName() const
Definition: board.h:228
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
PADS & Pads()
Definition: footprint.h:159
This file contains miscellaneous commonly used macros and functions.
wxPoint GetArcStart() const
Definition: pcb_shape.h:156
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:457
FP_TEXT & Reference()
Definition: footprint.h:458
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
like PAD_PTH, but not plated
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
wxString GetBuildVersion()
Get the full KiCad version string.
const wxPoint GetOrigin() const
Definition: eda_rect.h:101
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
FOOTPRINTS & Footprints()
Definition: board.h:233
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.cpp:385
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: pcb_shape.h:124
#define _(s)
static void idf_export_footprint(BOARD *aPcb, FOOTPRINT *aFootprint, IDF3_BOARD &aIDFBoard)
Retrieve information from all board footprints, adds drill holes to the DRILLED_HOLES or BOARD_OUTLIN...
Definition: export_idf.cpp:288
wxString ResolvePath(const wxString &aFileName)
Determines the full path of the given file name.
const int scale
Provide an extensible class to resolve 3D model paths.
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
double GetAngle() const
Definition: pcb_shape.h:107
Handle the component boundary box.
Definition: eda_rect.h:42
wxPoint GetPosition() const override
Definition: footprint.h:177
segment with non rounded ends
#define UNIT_MM
Definition: units_scales.h:31
static FILENAME_RESOLVER * resolver
Definition: export_idf.cpp:57
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:414
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
DRAWINGS & Drawings()
Definition: board.h:236
const wxSize GetSize() const
Definition: eda_rect.h:91
#define LINE_WIDTH
Definition: export_idf.cpp:54