KiCad PCB EDA Suite
export_hyperlynx.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 CERN
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <kiface_i.h>
25 #include <macros.h>
26 #include <pcb_edit_frame.h>
27 #include <board.h>
28 #include <board_item.h>
29 #include <footprint.h>
30 #include <track.h>
31 #include <zone.h>
32 #include <cstdio>
33 #include <vector>
34 #include <ki_exception.h>
35 #include <locale_io.h>
36 #include <reporter.h>
37 
39 
40 static double iu2hyp( double iu )
41 {
42  return iu / 1e9 / 0.0254;
43 }
44 
45 
46 class HYPERLYNX_EXPORTER;
47 
49 {
50 public:
51  friend class HYPERLYNX_EXPORTER;
52 
53  HYPERLYNX_PAD_STACK( BOARD* aBoard, const PAD* aPad );
54  HYPERLYNX_PAD_STACK( BOARD* aBoard, const VIA* aVia );
56 
57  bool isThrough() const
58  {
60  }
61 
62  bool operator==( const HYPERLYNX_PAD_STACK& other ) const
63  {
64  if( m_shape != other.m_shape )
65  return false;
66 
67  if( m_type != other.m_type )
68  return false;
69 
70  if( isThrough() && other.isThrough() && m_drill != other.m_drill )
71  return false;
72 
73  if( m_sx != other.m_sx )
74  return false;
75 
76  if( m_sy != other.m_sy )
77  return false;
78 
79  if( m_layers != other.m_layers )
80  return false;
81 
82  if( m_angle != other.m_angle )
83  return false;
84 
85  return true;
86  }
87 
88  bool isSMD() const
89  {
90  return m_type == PAD_ATTRIB_SMD;
91  }
92 
94  {
95  for( auto l : LSET::AllCuMask().Seq() )
96  {
97  if( m_layers[l] )
98  return l;
99  }
100  return F_Cu;
101  }
102 
103  void SetId( int id )
104  {
105  m_id = id;
106  }
107 
108  int GetId() const
109  {
110  return m_id;
111  }
112 
114  {
115  switch( m_shape )
116  {
117  case PAD_SHAPE_CIRCLE:
118  case PAD_SHAPE_OVAL:
119  case PAD_SHAPE_ROUNDRECT:
120  case PAD_SHAPE_RECT: return true;
121  default: return false;
122  }
123  }
124 
125  bool isEmpty() const
126  {
127  LSET layerMask = LSET::AllCuMask() & m_board->GetEnabledLayers();
128  LSET outLayers = m_layers & layerMask;
129 
130  return outLayers.none();
131  }
132 
133 private:
135  int m_id;
136  int m_drill;
138  int m_sx, m_sy;
139  double m_angle;
142 };
143 
144 
146 {
147 public:
149  {
150  }
151 
153 
154  virtual bool Run() override;
155 
156 private:
158  {
159  for( HYPERLYNX_PAD_STACK* p : m_padStacks )
160  {
161  if( *p == stack )
162  return p;
163  }
164 
165  stack.SetId( m_padStacks.size() );
166  m_padStacks.push_back( new HYPERLYNX_PAD_STACK( stack ) );
167 
168  return m_padStacks.back();
169  }
170 
171  const std::string formatPadShape( const HYPERLYNX_PAD_STACK& aStack )
172  {
173  int shapeId = 0;
174  char buf[1024];
175 
176  switch( aStack.m_shape )
177  {
178  case PAD_SHAPE_CIRCLE:
179  case PAD_SHAPE_OVAL: shapeId = 0; break;
180  case PAD_SHAPE_ROUNDRECT: shapeId = 2; break;
181  case PAD_SHAPE_RECT: shapeId = 1; break;
182  default:
183  shapeId = 0;
184 
185  if( m_reporter )
186  {
188  _( "File contains pad shapes that are not supported by the Hyperlynx exporter\n"
189  "(Supported shapes are oval, rectangle, circle.)\n"
190  "They have been exported as oval pads." ),
192  }
193  break;
194  }
195 
196  snprintf( buf, sizeof( buf ), "%d, %.9f, %.9f, %.1f, M", shapeId,
197  iu2hyp( aStack.m_sx ),
198  iu2hyp( aStack.m_sy ),
199  aStack.m_angle );
200 
201  return buf;
202  }
203 
204  bool generateHeaders();
205  bool writeBoardInfo();
206  bool writeStackupInfo();
207  bool writeDevices();
208  bool writePadStacks();
209  bool writeNets();
210  bool writeNetObjects( const std::vector<BOARD_ITEM*>& aObjects );
211 
212 
214 
215  const std::vector<BOARD_ITEM*> collectNetObjects( int netcode );
216 
217  std::vector<HYPERLYNX_PAD_STACK*> m_padStacks;
218  std::map<BOARD_ITEM*, HYPERLYNX_PAD_STACK*> m_padMap;
219 
220 
221  std::shared_ptr<FILE_OUTPUTFORMATTER> m_out;
222  int m_polyId;
223 };
224 
225 
227 {
228  m_board = aBoard;
229  m_sx = aPad->GetSize().x;
230  m_sy = aPad->GetSize().y;
231  m_angle = 180.0 - ( aPad->GetOrientation() / 10.0 );
232 
233  if( m_angle < 0.0 )
234  {
235  m_angle += 360.0;
236  }
237 
238  m_layers = aPad->GetLayerSet();
239  m_drill = aPad->GetDrillSize().x;
240  m_shape = aPad->GetShape();
242  m_id = 0;
243 }
244 
245 
247 {
248  m_board = aBoard;
249  m_sx = aVia->GetWidth();
250  m_sy = aVia->GetWidth();
251  m_angle = 0;
253  m_drill = aVia->GetDrillValue();
256  m_id = 0;
257 }
258 
259 
261 {
262  m_out->Print( 0, "{VERSION=2.14}\n" );
263  m_out->Print( 0, "{UNITS=ENGLISH LENGTH}\n\n" );
264  return true;
265 }
266 
267 
269 {
270  LSET layerMask = LSET::AllCuMask() & m_board->GetEnabledLayers();
271  LSET outLayers = aStack.m_layers & layerMask;
272 
273  if( outLayers.none() )
274  return;
275 
276  m_out->Print( 0, "{PADSTACK=%d, %.9f\n", aStack.m_id, iu2hyp( aStack.m_drill ) );
277 
278  if( outLayers == layerMask )
279  {
280  m_out->Print( 1, "(\"%s\", %s)\n", "MDEF", formatPadShape( aStack ).c_str() );
281  }
282  else
283  {
284  for( PCB_LAYER_ID l : outLayers.Seq() )
285  {
286  m_out->Print( 1, "(\"%s\", %s)\n", (const char*) m_board->GetLayerName( l ).c_str(),
287  formatPadShape( aStack ).c_str() );
288  }
289  }
290 
291  m_out->Print( 0, "}\n\n" );
292 }
293 
294 
296 {
297  SHAPE_POLY_SET outlines;
298 
299  m_out->Print( 0, "{BOARD \"%s\"\n", (const char*) m_board->GetFileName().c_str() );
300 
301  if( !m_board->GetBoardPolygonOutlines( outlines ) )
302  {
303  wxLogError( _( "Board outline is malformed. Run DRC for a full analysis." ) );
304  return false;
305  }
306 
307  for( int o = 0; o < outlines.OutlineCount(); o++ )
308  {
309  const SHAPE_LINE_CHAIN& outl = outlines.COutline( o );
310 
311  for( int i = 0; i < outl.SegmentCount(); i++ )
312  {
313  const auto& s = outl.CSegment( i );
314  m_out->Print( 1, "(PERIMETER_SEGMENT X1=%.9f Y1=%.9f X2=%.9f Y2=%.9f)\n",
315  iu2hyp( s.A.x ), iu2hyp( s.A.y ), iu2hyp( s.B.x ), iu2hyp( s.B.y ) );
316  }
317  }
318 
319  m_out->Print( 0, "}\n\n" );
320 
321  return true;
322 }
323 
324 
326 {
327  /* Format:
328  * {STACKUP
329  * (SIGNAL T=thickness [P=plating_thickness] [C=constant] L=layer_name [M=material_name]) [comment]
330  * (DIELECTRIC T=thickness [C=constant] [L=layer_name] [M=material_name]) [comment]
331  * }
332  * name lenght is <= 20 chars
333  */
334 
336 
337  // Get the board physical stackup structure
339 
340  m_out->Print( 0, "{STACKUP\n" );
341 
342  wxString layer_name; // The last copper layer name used in stackup
343 
344  for( BOARD_STACKUP_ITEM* item: stackup.GetList() )
345  {
346  if( item->GetType() == BS_ITEM_TYPE_COPPER )
347  {
348  layer_name = m_board->GetLayerName( item->GetBrdLayerId() );
349  int plating_thickness = 0;
350  double resistivity = 1.724e-8; // Good for copper
351  m_out->Print( 1, "(SIGNAL T=%g P=%g C=%g L=\"%.20s\" M=COPPER)\n",
352  iu2hyp( item->GetThickness( 0 ) ),
353  iu2hyp( plating_thickness ),
354  resistivity,
355  TO_UTF8( layer_name ) );
356  }
357  else if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
358  {
359  if( item->GetSublayersCount() < 2 )
360  {
361  m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"DE_%.17s\" M=\"%.20s\")\n",
362  iu2hyp( item->GetThickness( 0 ) ),
363  item->GetEpsilonR( 0 ),
364  TO_UTF8( layer_name ),
365  TO_UTF8( item->GetMaterial( 0 ) ) );
366  }
367  else for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
368  {
369  m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"DE%d_%.16s\" M=\"%.20s\")\n",
370  iu2hyp( item->GetThickness( idx ) ),
371  item->GetEpsilonR( idx ),
372  idx, TO_UTF8( layer_name ),
373  TO_UTF8( item->GetMaterial( idx ) ) );
374  }
375  }
376  }
377 
378  m_out->Print( 0, "}\n\n" );
379 
380  return true;
381 }
382 
383 
385 {
386  m_out->Print( 0, "{DEVICES\n" );
387 
388  for( FOOTPRINT* footprint : m_board->Footprints() )
389  {
390  wxString ref = footprint->GetReference();
391  wxString layerName = m_board->GetLayerName( footprint->GetLayer() );
392 
393  if( ref.IsEmpty() )
394  ref = "EMPTY";
395 
396  m_out->Print( 1, "(? REF=\"%s\" L=\"%s\")\n", (const char*) ref.c_str(),
397  (const char*) layerName.c_str() );
398  }
399  m_out->Print( 0, "}\n\n" );
400 
401  return true;
402 }
403 
404 
406 {
407  for( FOOTPRINT* footprint : m_board->Footprints() )
408  {
409  for( PAD* pad : footprint->Pads() )
410  {
412  m_padMap[pad] = ps;
413  }
414  }
415 
416  for( TRACK* trk : m_board->Tracks() )
417  {
418  if( VIA* via = dyn_cast<VIA*>( trk ) )
419  {
421  m_padMap[via] = ps;
422  }
423  }
424 
425  for( HYPERLYNX_PAD_STACK* pstack : m_padStacks )
426  writeSinglePadStack( *pstack );
427 
428  return true;
429 }
430 
431 
432 bool HYPERLYNX_EXPORTER::writeNetObjects( const std::vector<BOARD_ITEM*>& aObjects )
433 {
434  for( BOARD_ITEM* item : aObjects )
435  {
436  if( PAD* pad = dyn_cast<PAD*>( item ) )
437  {
438  auto pstackIter = m_padMap.find( pad );
439 
440  if( pstackIter != m_padMap.end() )
441  {
442  wxString ref = pad->GetParent()->GetReference();
443 
444  if( ref.IsEmpty() )
445  ref = "EMPTY";
446 
447  wxString padName = pad->GetName();
448 
449  if( padName.IsEmpty() )
450  padName = "1";
451 
452 
453  m_out->Print( 1, "(PIN X=%.10f Y=%.10f R=\"%s.%s\" P=%d)\n",
454  iu2hyp( pad->GetPosition().x ), iu2hyp( pad->GetPosition().y ),
455  (const char*) ref.c_str(), (const char*) padName.c_str(),
456  pstackIter->second->GetId() );
457  }
458  }
459  else if( VIA* via = dyn_cast<VIA*>( item ) )
460  {
461  auto pstackIter = m_padMap.find( via );
462 
463  if( pstackIter != m_padMap.end() )
464  {
465  m_out->Print( 1, "(VIA X=%.10f Y=%.10f P=%d)\n", iu2hyp( via->GetPosition().x ),
466  iu2hyp( via->GetPosition().y ), pstackIter->second->GetId() );
467  }
468  }
469  else if( TRACK* track = dyn_cast<TRACK*>( item ) )
470  {
471  const wxString layerName = m_board->GetLayerName( track->GetLayer() );
472 
473  m_out->Print( 1, "(SEG X1=%.10f Y1=%.10f X2=%.10f Y2=%.10f W=%.10f L=\"%s\")\n",
474  iu2hyp( track->GetStart().x ), iu2hyp( track->GetStart().y ),
475  iu2hyp( track->GetEnd().x ), iu2hyp( track->GetEnd().y ),
476  iu2hyp( track->GetWidth() ), (const char*) layerName.c_str() );
477  }
478  else if( ZONE* zone = dyn_cast<ZONE*>( item ) )
479  {
480  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
481  {
482  const wxString layerName = m_board->GetLayerName( layer );
483  SHAPE_POLY_SET filledShape = zone->GetFilledPolysList( layer );
484 
485  filledShape.Simplify( SHAPE_POLY_SET::PM_FAST );
486 
487  for( int i = 0; i < filledShape.OutlineCount(); i++ )
488  {
489  const SHAPE_LINE_CHAIN& outl = filledShape.COutline( i );
490 
491  auto p0 = outl.CPoint( 0 );
492  m_out->Print( 1, "{POLYGON T=POUR L=\"%s\" ID=%d X=%.10f Y=%.10f\n",
493  (const char*) layerName.c_str(), m_polyId, iu2hyp( p0.x ),
494  iu2hyp( p0.y ) );
495 
496  for( int v = 0; v < outl.PointCount(); v++ )
497  {
498  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n", iu2hyp( outl.CPoint( v ).x ),
499  iu2hyp( outl.CPoint( v ).y ) );
500  }
501 
502  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n", iu2hyp( p0.x ), iu2hyp( p0.y ) );
503  m_out->Print( 1, "}\n" );
504 
505  for( int h = 0; h < filledShape.HoleCount( i ); h++ )
506  {
507  const SHAPE_LINE_CHAIN& holeShape = filledShape.CHole( i, h );
508  VECTOR2I ph0 = holeShape.CPoint( 0 );
509 
510  m_out->Print( 1, "{POLYVOID ID=%d X=%.10f Y=%.10f\n", m_polyId,
511  iu2hyp( ph0.x ), iu2hyp( ph0.y ) );
512 
513  for( int v = 0; v < holeShape.PointCount(); v++ )
514  {
515  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
516  iu2hyp( holeShape.CPoint( v ).x ),
517  iu2hyp( holeShape.CPoint( v ).y ) );
518  }
519 
520  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
521  iu2hyp( ph0.x ), iu2hyp( ph0.y ) );
522  m_out->Print( 1, "}\n" );
523  }
524 
525  m_polyId++;
526  }
527  }
528  }
529  }
530 
531  return true;
532 }
533 
534 
535 const std::vector<BOARD_ITEM*> HYPERLYNX_EXPORTER::collectNetObjects( int netcode )
536 {
537  std::vector<BOARD_ITEM*> rv;
538 
539  auto check =
540  [&]( BOARD_CONNECTED_ITEM* item ) -> bool
541  {
542  if( ( item->GetLayerSet() & LSET::AllCuMask() ).none() )
543  return false;
544 
545  if( item->GetNetCode() == netcode || ( netcode < 0 && item->GetNetCode() <= 0 ) )
546  return true;
547 
548  return false;
549  };
550 
551  for( FOOTPRINT* footprint : m_board->Footprints() )
552  {
553  for( PAD* pad : footprint->Pads() )
554  {
555  if( check( pad ) )
556  rv.push_back( pad );
557  }
558  }
559 
560  for( TRACK* item : m_board->Tracks() )
561  {
562  if( check( item ) )
563  rv.push_back( item );
564  }
565 
566  for( ZONE* zone : m_board->Zones() )
567  {
568  if( check( zone ) )
569  rv.push_back( zone );
570  }
571 
572  return rv;
573 }
574 
575 
577 {
578  m_polyId = 1;
579 
580  for( const auto netInfo : m_board->GetNetInfo() )
581  {
582  int netcode = netInfo->GetNetCode();
583  bool isNullNet = netInfo->GetNetCode() <= 0 || netInfo->GetNetname().IsEmpty();
584 
585  if( isNullNet )
586  continue;
587 
588  auto netObjects = collectNetObjects( netcode );
589 
590  if( netObjects.size() )
591  {
592  m_out->Print( 0, "{NET=\"%s\"\n", (const char*) netInfo->GetNetname().c_str() );
593  writeNetObjects( netObjects );
594  m_out->Print( 0, "}\n\n" );
595  }
596  }
597 
598  auto nullNetObjects = collectNetObjects( -1 );
599 
600  int idx = 0;
601 
602  for( auto item : nullNetObjects )
603  {
604  m_out->Print( 0, "{NET=\"EmptyNet%d\"\n", idx );
605  writeNetObjects( { item } );
606  m_out->Print( 0, "}\n\n" );
607  idx++;
608  }
609 
610  return true;
611 }
612 
613 
615 {
616  LOCALE_IO toggle; // toggles on, then off, the C locale.
617 
618  try
619  {
620  m_out.reset( new FILE_OUTPUTFORMATTER( m_outputFilePath.GetFullPath() ) );
621 
622  generateHeaders();
623  writeBoardInfo();
625  writeDevices();
626  writePadStacks();
627  writeNets();
628  }
629  catch( IO_ERROR& )
630  {
631  return false;
632  }
633 
634  return true;
635 }
636 
637 
638 bool ExportBoardToHyperlynx( BOARD* aBoard, const wxFileName& aPath )
639 {
640  HYPERLYNX_EXPORTER exporter;
641  exporter.SetBoard( aBoard );
642  exporter.SetOutputFilename( aPath );
643  return exporter.Run();
644 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
bool writeNetObjects(const std::vector< BOARD_ITEM * > &aObjects)
Definition: track.h:343
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
Definition: lset.cpp:170
bool ExportBoardToHyperlynx(BOARD *aBoard, const wxFileName &aPath)
int OutlineCount() const
Return the number of vertices in a given outline/hole.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:342
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:1922
ZONES & Zones()
Definition: board.h:311
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
PAD_ATTR_T
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:78
bool operator==(const HYPERLYNX_PAD_STACK &other) const
int IsSupportedByExporter() const
Manage layers needed to make a physical board.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:593
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:754
PAD_SHAPE_T GetShape() const
Definition: pad.h:169
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings Returns a bit-mask of all t...
Definition: board.cpp:447
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
int PointCount() const
Function PointCount()
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
const wxString & GetFileName() const
Definition: board.h:300
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
PAD_SHAPE_T
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition: pad_shapes.h:32
std::vector< HYPERLYNX_PAD_STACK * > m_padStacks
This file contains miscellaneous commonly used macros and functions.
void SetOutputFilename(const wxFileName &aPath)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
const VECTOR2I & CPoint(int aIndex) const
Function Point()
HYPERLYNX_PAD_STACK * addPadStack(HYPERLYNX_PAD_STACK stack)
const wxSize & GetDrillSize() const
Definition: pad.h:242
BOARD_STACKUP & GetStackupDescriptor()
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
double GetOrientation() const
Return the rotation angle of the pad in a variety of units (the basic call returns tenths of degrees)...
Definition: pad.h:349
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: track.cpp:173
Represent a set of closed polygons.
std::map< BOARD_ITEM *, HYPERLYNX_PAD_STACK * > m_padMap
FOOTPRINTS & Footprints()
Definition: board.h:305
const wxSize & GetSize() const
Definition: pad.h:232
HYPERLYNX_PAD_STACK(BOARD *aBoard, const PAD *aPad)
void Simplify(POLYGON_MODE aFastMode)
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: pad.h:368
Manage one layer needed to make a physical board.
Definition: board_stackup.h:89
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
int SegmentCount() const
Function SegmentCount()
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
PCB_LAYER_ID getSMDLayer() const
void writeSinglePadStack(HYPERLYNX_PAD_STACK &aStack)
int GetWidth() const
Definition: track.h:110
const SEG CSegment(int aIndex) const
Function CSegment()
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
void SetBoard(BOARD *aBoard)
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const std::vector< BOARD_ITEM * > collectNetObjects(int netcode)
Plated through hole pad.
Definition: pad_shapes.h:80
std::shared_ptr< FILE_OUTPUTFORMATTER > m_out
virtual bool Run() override
Used for text file output.
Definition: richio.h:453
Definition: pad.h:60
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:75
static double iu2hyp(double iu)
TRACKS & Tracks()
Definition: board.h:302
Definition: track.h:83
const std::string formatPadShape(const HYPERLYNX_PAD_STACK &aStack)