KiCad PCB EDA Suite
export_idf.cpp File Reference
#include <list>
#include <locale_io.h>
#include <macros.h>
#include <pcb_edit_frame.h>
#include <board.h>
#include <board_design_settings.h>
#include <footprint.h>
#include <fp_lib_table.h>
#include <fp_shape.h>
#include <idf_parser.h>
#include <pad.h>
#include <build_version.h>
#include <wx/msgdlg.h>
#include "project.h"
#include "kiway.h"
#include "3d_cache/3d_cache.h"
#include "filename_resolver.h"
#include <base_units.h>

Go to the source code of this file.

Macros

#define LINE_WIDTH   (pcbIUScale.mmToIU( 0.1 ))
 

Functions

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 output as an IDFv3 compliant #BOARD_OUTLINE section. More...
 
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_OUTLINE section as appropriate, Compiles data for the PLACEMENT section and compiles data for the library ELECTRICAL section. More...
 

Variables

static FILENAME_RESOLVERresolver
 

Macro Definition Documentation

◆ LINE_WIDTH

#define LINE_WIDTH   (pcbIUScale.mmToIU( 0.1 ))

Definition at line 49 of file export_idf.cpp.

Function Documentation

◆ idf_export_footprint()

static void idf_export_footprint ( BOARD aPcb,
FOOTPRINT aFootprint,
IDF3_BOARD &  aIDFBoard 
)
static

Retrieve information from all board footprints, adds drill holes to the DRILLED_HOLES or BOARD_OUTLINE section as appropriate, Compiles data for the PLACEMENT section and compiles data for the library ELECTRICAL section.

Definition at line 274 of file export_idf.cpp.

275{
276 // Reference Designator
277 std::string crefdes = TO_UTF8( aFootprint->Reference().GetShownText() );
278
279 wxString libraryName = aFootprint->GetFPID().GetLibNickname();
280 wxString footprintBasePath = wxEmptyString;
281
282 if( aPcb->GetProject() )
283 {
284 const FP_LIB_TABLE_ROW* fpRow = nullptr;
285
286 try
287 {
288 fpRow = aPcb->GetProject()->PcbFootprintLibs()->FindRow( libraryName, false );
289 }
290 catch( ... )
291 {
292 // Not found: do nothing
293 }
294
295 if( fpRow )
296 footprintBasePath = fpRow->GetFullURI( true );
297 }
298
299 if( crefdes.empty() || !crefdes.compare( "~" ) )
300 {
301 std::string cvalue = TO_UTF8( aFootprint->Value().GetShownText() );
302
303 // if both the RefDes and Value are empty or set to '~' the board owns the part,
304 // otherwise associated parts of the footprint must be marked NOREFDES.
305 if( cvalue.empty() || !cvalue.compare( "~" ) )
306 crefdes = "BOARD";
307 else
308 crefdes = "NOREFDES";
309 }
310
311 // TODO: If footprint cutouts are supported we must add code here
312 // for( EDA_ITEM* item = aFootprint->GraphicalItems(); item != NULL; item = item->Next() )
313 // {
314 // if( item->Type() != PCB_FP_SHAPE_T || item->GetLayer() != Edge_Cuts )
315 // continue;
316 // code to export cutouts
317 // }
318
319 // Export pads
320 double drill, x, y;
321 double scale = aIDFBoard.GetUserScale();
322 IDF3::KEY_PLATING kplate;
323 std::string pintype;
324 std::string tstr;
325
326 double dx, dy;
327
328 aIDFBoard.GetUserOffset( dx, dy );
329
330 for( auto pad : aFootprint->Pads() )
331 {
332 drill = (double) pad->GetDrillSize().x * scale;
333 x = pad->GetPosition().x * scale + dx;
334 y = -pad->GetPosition().y * scale + dy;
335
336 // Export the hole on the edge layer
337 if( drill > 0.0 )
338 {
339 // plating
340 if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
341 kplate = IDF3::NPTH;
342 else
343 kplate = IDF3::PTH;
344
345 // hole type
346 tstr = TO_UTF8( pad->GetNumber() );
347
348 if( tstr.empty() || !tstr.compare( "0" ) || !tstr.compare( "~" )
349 || ( kplate == IDF3::NPTH )
350 || ( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ) )
351 pintype = "MTG";
352 else
353 pintype = "PIN";
354
355 // fields:
356 // 1. hole dia. : float
357 // 2. X coord : float
358 // 3. Y coord : float
359 // 4. plating : PTH | NPTH
360 // 5. Assoc. part : BOARD | NOREFDES | PANEL | {"refdes"}
361 // 6. type : PIN | VIA | MTG | TOOL | { "other" }
362 // 7. owner : MCAD | ECAD | UNOWNED
363 if( ( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG )
364 && ( pad->GetDrillSize().x != pad->GetDrillSize().y ) )
365 {
366 // NOTE: IDF does not have direct support for slots;
367 // slots are implemented as a board cutout and we
368 // cannot represent plating or reference designators
369
370 double dlength = pad->GetDrillSize().y * scale;
371
372 // NOTE: The orientation of footprints and pads have
373 // the opposite sense due to KiCad drawing on a
374 // screen with a LH coordinate system
375 double angle = pad->GetOrientation().AsDegrees();
376
377 // NOTE: Since this code assumes the scenario where
378 // GetDrillSize().y is the length but idf_parser.cpp
379 // assumes a length along the X axis, the orientation
380 // must be shifted +90 deg when GetDrillSize().y is
381 // the major axis.
382
383 if( dlength < drill )
384 {
385 std::swap( drill, dlength );
386 }
387 else
388 {
389 angle += 90.0;
390 }
391
392 // NOTE: KiCad measures a slot's length from end to end
393 // rather than between the centers of the arcs
394 dlength -= drill;
395
396 aIDFBoard.AddSlot( drill, dlength, angle, x, y );
397 }
398 else
399 {
400 IDF_DRILL_DATA *dp = new IDF_DRILL_DATA( drill, x, y, kplate, crefdes,
401 pintype, IDF3::ECAD );
402
403 if( !aIDFBoard.AddDrill( dp ) )
404 {
405 delete dp;
406
407 std::ostringstream ostr;
408 ostr << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__;
409 ostr << "(): could not add drill";
410
411 throw std::runtime_error( ostr.str() );
412 }
413 }
414 }
415 }
416
417 // add any valid models to the library item list
418 std::string refdes;
419
420 IDF3_COMPONENT* comp = nullptr;
421
422 auto sM = aFootprint->Models().begin();
423 auto eM = aFootprint->Models().end();
424 wxFileName idfFile;
425 wxString idfExt;
426
427 while( sM != eM )
428 {
429 if( !sM->m_Show )
430 {
431 ++sM;
432 continue;
433 }
434
435 idfFile.Assign( resolver->ResolvePath( sM->m_Filename, footprintBasePath ) );
436 idfExt = idfFile.GetExt();
437
438 if( idfExt.Cmp( wxT( "idf" ) ) && idfExt.Cmp( wxT( "IDF" ) ) )
439 {
440 ++sM;
441 continue;
442 }
443
444 if( refdes.empty() )
445 {
446 refdes = TO_UTF8( aFootprint->Reference().GetShownText() );
447
448 // NOREFDES cannot be used or else the software gets confused
449 // when writing out the placement data due to conflicting
450 // placement and layer specifications; to work around this we
451 // create a (hopefully) unique refdes for our exported part.
452 if( refdes.empty() || !refdes.compare( "~" ) )
453 refdes = aIDFBoard.GetNewRefDes();
454 }
455
456 IDF3_COMP_OUTLINE* outline;
457
458 outline = aIDFBoard.GetComponentOutline( idfFile.GetFullPath() );
459
460 if( !outline )
461 throw( std::runtime_error( aIDFBoard.GetError() ) );
462
463 double rotz = aFootprint->GetOrientation().AsDegrees();
464 double locx = sM->m_Offset.x * 25.4; // part offsets are in inches
465 double locy = sM->m_Offset.y * 25.4;
466 double locz = sM->m_Offset.z * 25.4;
467 double lrot = sM->m_Rotation.z;
468
469 bool top = ( aFootprint->GetLayer() == B_Cu ) ? false : true;
470
471 if( top )
472 {
473 locy = -locy;
474 RotatePoint( &locx, &locy, aFootprint->GetOrientation() );
475 locy = -locy;
476 }
477
478 if( !top )
479 {
480 lrot = -lrot;
481 RotatePoint( &locx, &locy, aFootprint->GetOrientation() );
482 locy = -locy;
483
484 rotz = 180.0 - rotz;
485
486 if( rotz >= 360.0 )
487 while( rotz >= 360.0 ) rotz -= 360.0;
488
489 if( rotz <= -360.0 )
490 while( rotz <= -360.0 ) rotz += 360.0;
491 }
492
493 if( comp == nullptr )
494 comp = aIDFBoard.FindComponent( refdes );
495
496 if( comp == nullptr )
497 {
498 comp = new IDF3_COMPONENT( &aIDFBoard );
499
500 if( comp == nullptr )
501 throw( std::runtime_error( aIDFBoard.GetError() ) );
502
503 comp->SetRefDes( refdes );
504
505 if( top )
506 {
507 comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
508 -aFootprint->GetPosition().y * scale + dy,
509 rotz, IDF3::LYR_TOP );
510 }
511 else
512 {
513 comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
514 -aFootprint->GetPosition().y * scale + dy,
515 rotz, IDF3::LYR_BOTTOM );
516 }
517
518 comp->SetPlacement( IDF3::PS_ECAD );
519
520 aIDFBoard.AddComponent( comp );
521 }
522 else
523 {
524 double refX, refY, refA;
525 IDF3::IDF_LAYER side;
526
527 if( ! comp->GetPosition( refX, refY, refA, side ) )
528 {
529 // place the item
530 if( top )
531 {
532 comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
533 -aFootprint->GetPosition().y * scale + dy,
534 rotz, IDF3::LYR_TOP );
535 }
536 else
537 {
538 comp->SetPosition( aFootprint->GetPosition().x * scale + dx,
539 -aFootprint->GetPosition().y * scale + dy,
540 rotz, IDF3::LYR_BOTTOM );
541 }
542
543 comp->SetPlacement( IDF3::PS_ECAD );
544
545 }
546 else
547 {
548 // check that the retrieved component matches this one
549 refX = refX - ( aFootprint->GetPosition().x * scale + dx );
550 refY = refY - ( -aFootprint->GetPosition().y * scale + dy );
551 refA = refA - rotz;
552 refA *= refA;
553 refX *= refX;
554 refY *= refY;
555 refX += refY;
556
557 // conditions: same side, X,Y coordinates within 10 microns,
558 // angle within 0.01 degree
559 if( ( top && side == IDF3::LYR_BOTTOM ) || ( !top && side == IDF3::LYR_TOP )
560 || ( refA > 0.0001 ) || ( refX > 0.0001 ) )
561 {
562 comp->GetPosition( refX, refY, refA, side );
563
564 std::ostringstream ostr;
565 ostr << "* " << __FILE__ << ":" << __LINE__ << ":" << __FUNCTION__ << "():\n";
566 ostr << "* conflicting Reference Designator '" << refdes << "'\n";
567 ostr << "* X loc: " << ( aFootprint->GetPosition().x * scale + dx);
568 ostr << " vs. " << refX << "\n";
569 ostr << "* Y loc: " << ( -aFootprint->GetPosition().y * scale + dy);
570 ostr << " vs. " << refY << "\n";
571 ostr << "* angle: " << rotz;
572 ostr << " vs. " << refA << "\n";
573
574 if( top )
575 ostr << "* TOP vs. ";
576 else
577 ostr << "* BOTTOM vs. ";
578
579 if( side == IDF3::LYR_TOP )
580 ostr << "TOP";
581 else
582 ostr << "BOTTOM";
583
584 throw( std::runtime_error( ostr.str() ) );
585 }
586 }
587 }
588
589 // create the local data ...
590 IDF3_COMP_OUTLINE_DATA* data = new IDF3_COMP_OUTLINE_DATA( comp, outline );
591
592 data->SetOffsets( locx, locy, locz, lrot );
593 comp->AddOutlineData( data );
594 ++sM;
595 }
596}
PROJECT * GetProject() const
Definition: board.h:440
double AsDegrees() const
Definition: eda_angle.h:149
wxString ResolvePath(const wxString &aFileName, const wxString &aWorkingPath)
Determines the full path of the given file name.
EDA_ANGLE GetOrientation() const
Definition: footprint.h:191
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: footprint.h:200
PADS & Pads()
Definition: footprint.h:170
const LIB_ID & GetFPID() const
Definition: footprint.h:212
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:567
std::vector< FP_3DMODEL > & Models()
Definition: footprint.h:184
VECTOR2I GetPosition() const override
Definition: footprint.h:188
FP_TEXT & Reference()
Definition: footprint.h:568
Hold a record identifying a library accessed by the appropriate footprint library PLUGIN object in th...
Definition: fp_lib_table.h:41
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
virtual wxString GetShownText(int aDepth=0, bool aAllowExtraText=true) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:415
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Definition: lib_id.h:87
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
virtual FP_LIB_TABLE * PcbFootprintLibs(KIWAY &aKiway)
Return the table of footprint libraries.
Definition: project.cpp:324
static FILENAME_RESOLVER * resolver
Definition: export_idf.cpp:52
@ B_Cu
Definition: layer_ids.h:95
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
@ NPTH
like PAD_PTH, but not plated
@ PAD_DRILL_SHAPE_OBLONG
Definition: pad_shapes.h:71
const int scale
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183

References PNS::angle(), EDA_ANGLE::AsDegrees(), B_Cu, FP_LIB_TABLE::FindRow(), FOOTPRINT::GetFPID(), LIB_TABLE_ROW::GetFullURI(), FOOTPRINT::GetLayer(), LIB_ID::GetLibNickname(), FOOTPRINT::GetOrientation(), FOOTPRINT::GetPosition(), BOARD::GetProject(), FP_TEXT::GetShownText(), FOOTPRINT::Models(), NPTH, pad, PAD_DRILL_SHAPE_OBLONG, FOOTPRINT::Pads(), PROJECT::PcbFootprintLibs(), FOOTPRINT::Reference(), FILENAME_RESOLVER::ResolvePath(), resolver, RotatePoint(), scale, TO_UTF8, FOOTPRINT::Value(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PCB_EDIT_FRAME::Export_IDF3().

◆ idf_export_outline()

static void idf_export_outline ( BOARD aPcb,
IDF3_BOARD &  aIDFBoard 
)
static

Retrieve line segment information from the edge layer and compiles the data into a form which can be output as an IDFv3 compliant #BOARD_OUTLINE section.

Definition at line 59 of file export_idf.cpp.

60{
61 double scale = aIDFBoard.GetUserScale();
62
63 PCB_SHAPE* graphic; // KiCad graphical item
64 IDF_POINT sp, ep; // start and end points from KiCad item
65
66 std::list< IDF_SEGMENT* > lines; // IDF intermediate form of KiCad graphical item
67 IDF_OUTLINE* outline = nullptr; // graphical items forming an outline or cutout
68
69 // NOTE: IMPLEMENTATION
70 // If/when component cutouts are allowed, we must implement them separately. Cutouts
71 // must be added to the board outline section and not to the Other Outline section.
72 // The footprint cutouts should be handled via the idf_export_footprint() routine.
73
74 double offX, offY;
75 aIDFBoard.GetUserOffset( offX, offY );
76
77 // Retrieve segments and arcs from the board
78 for( BOARD_ITEM* item : aPcb->Drawings() )
79 {
80 if( item->Type() != PCB_SHAPE_T || item->GetLayer() != Edge_Cuts )
81 continue;
82
83 graphic = (PCB_SHAPE*) item;
84
85 switch( graphic->GetShape() )
86 {
88 {
89 if( graphic->GetStart() == graphic->GetEnd() )
90 break;
91
92 sp.x = graphic->GetStart().x * scale + offX;
93 sp.y = -graphic->GetStart().y * scale + offY;
94 ep.x = graphic->GetEnd().x * scale + offX;
95 ep.y = -graphic->GetEnd().y * scale + offY;
96 IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep );
97
98 if( seg )
99 lines.push_back( seg );
100
101 break;
102 }
103
104 case SHAPE_T::RECT:
105 {
106 if( graphic->GetStart() == graphic->GetEnd() )
107 break;
108
109 double top = graphic->GetStart().y * scale + offY;
110 double left = graphic->GetStart().x * scale + offX;
111 double bottom = graphic->GetEnd().y * scale + offY;
112 double right = graphic->GetEnd().x * scale + offX;
113
114 IDF_POINT corners[4];
115 corners[0] = IDF_POINT( left, top );
116 corners[1] = IDF_POINT( right, top );
117 corners[2] = IDF_POINT( right, bottom );
118 corners[3] = IDF_POINT( left, bottom );
119
120 lines.push_back( new IDF_SEGMENT( corners[0], corners[1] ) );
121 lines.push_back( new IDF_SEGMENT( corners[1], corners[2] ) );
122 lines.push_back( new IDF_SEGMENT( corners[2], corners[3] ) );
123 lines.push_back( new IDF_SEGMENT( corners[3], corners[0] ) );
124 break;
125 }
126
127 case SHAPE_T::ARC:
128 {
129 if( graphic->GetCenter() == graphic->GetStart() )
130 break;
131
132 sp.x = graphic->GetCenter().x * scale + offX;
133 sp.y = -graphic->GetCenter().y * scale + offY;
134 ep.x = graphic->GetStart().x * scale + offX;
135 ep.y = -graphic->GetStart().y * scale + offY;
136 IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep, -graphic->GetArcAngle().AsDegrees(), true );
137
138 if( seg )
139 lines.push_back( seg );
140
141 break;
142 }
143
144 case SHAPE_T::CIRCLE:
145 {
146 if( graphic->GetRadius() == 0 )
147 break;
148
149 sp.x = graphic->GetCenter().x * scale + offX;
150 sp.y = -graphic->GetCenter().y * scale + offY;
151 ep.x = sp.x - graphic->GetRadius() * scale;
152 ep.y = sp.y;
153
154 // Circles must always have an angle of +360 deg. to appease
155 // quirky MCAD implementations of IDF.
156 IDF_SEGMENT* seg = new IDF_SEGMENT( sp, ep, 360.0, true );
157
158 if( seg )
159 lines.push_back( seg );
160
161 break;
162 }
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 = nullptr;
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 = nullptr;
204 }
205
206 return;
207
208UseBoundingBox:
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; there is always some uncertainty in the
223 // board dimensions computed via ComputeBoundingBox() since this depends on the individual
224 // footprint entities.
225 BOX2I bbbox = aPcb->GetBoardEdgesBoundingBox();
226
227 // convert to mm and compensate for an assumed LINE_WIDTH line thickness
228 double x = ( bbbox.GetOrigin().x + LINE_WIDTH / 2 ) * scale + offX;
229 double y = ( bbbox.GetOrigin().y + LINE_WIDTH / 2 ) * scale + offY;
230 double dx = ( bbbox.GetSize().x - LINE_WIDTH ) * scale;
231 double dy = ( bbbox.GetSize().y - LINE_WIDTH ) * scale;
232
233 double px[4], py[4];
234 px[0] = x;
235 py[0] = y;
236
237 px[1] = x;
238 py[1] = y + dy;
239
240 px[2] = x + dx;
241 py[2] = y + dy;
242
243 px[3] = x + dx;
244 py[3] = y;
245
246 IDF_POINT p1, p2;
247
248 p1.x = px[3];
249 p1.y = py[3];
250 p2.x = px[0];
251 p2.y = py[0];
252
253 outline->push( new IDF_SEGMENT( p1, p2 ) );
254
255 for( int i = 1; i < 4; ++i )
256 {
257 p1.x = px[i - 1];
258 p1.y = py[i - 1];
259 p2.x = px[i];
260 p2.y = py[i];
261
262 outline->push( new IDF_SEGMENT( p1, p2 ) );
263 }
264
265 aIDFBoard.AddBoardOutline( outline );
266}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:823
DRAWINGS & Drawings()
Definition: board.h:310
const Vec & GetOrigin() const
Definition: box2.h:183
const Vec & GetSize() const
Definition: box2.h:179
EDA_ANGLE GetArcAngle() const
Definition: eda_shape.cpp:573
int GetRadius() const
Definition: eda_shape.cpp:511
SHAPE_T GetShape() const
Definition: eda_shape.h:113
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition: eda_shape.h:145
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition: eda_shape.h:120
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.h:67
#define LINE_WIDTH
Definition: export_idf.cpp:49
@ Edge_Cuts
Definition: layer_ids.h:113
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88

References ARC, EDA_ANGLE::AsDegrees(), CIRCLE, BOARD::Drawings(), Edge_Cuts, EDA_SHAPE::GetArcAngle(), BOARD::GetBoardEdgesBoundingBox(), PCB_SHAPE::GetCenter(), EDA_SHAPE::GetEnd(), BOX2< Vec >::GetOrigin(), EDA_SHAPE::GetRadius(), EDA_SHAPE::GetShape(), BOX2< Vec >::GetSize(), EDA_SHAPE::GetStart(), left, LINE_WIDTH, PCB_SHAPE_T, RECT, right, scale, SEGMENT, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PCB_EDIT_FRAME::Export_IDF3().

Variable Documentation

◆ resolver