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