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