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