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_base.h>
25 #include <macros.h>
26 #include <pcb_edit_frame.h>
27 #include <board.h>
28 #include <board_design_settings.h>
29 #include <board_item.h>
30 #include <footprint.h>
31 #include <pad.h>
32 #include <pcb_track.h>
33 #include <zone.h>
34 #include <cstdio>
35 #include <vector>
36 #include <ki_exception.h>
37 #include <locale_io.h>
38 #include <reporter.h>
39 #include <wx/log.h>
40 
42 
43 static double iu2hyp( double iu )
44 {
45  return iu / 1e9 / 0.0254;
46 }
47 
48 
49 class HYPERLYNX_EXPORTER;
50 
52 {
53 public:
54  friend class HYPERLYNX_EXPORTER;
55 
56  HYPERLYNX_PAD_STACK( BOARD* aBoard, const PAD* aPad );
57  HYPERLYNX_PAD_STACK( BOARD* aBoard, const PCB_VIA* aVia );
59 
60  bool isThrough() const
61  {
63  }
64 
65  bool operator==( const HYPERLYNX_PAD_STACK& other ) const
66  {
67  if( m_shape != other.m_shape )
68  return false;
69 
70  if( m_type != other.m_type )
71  return false;
72 
73  if( isThrough() && other.isThrough() && m_drill != other.m_drill )
74  return false;
75 
76  if( m_sx != other.m_sx )
77  return false;
78 
79  if( m_sy != other.m_sy )
80  return false;
81 
82  if( m_layers != other.m_layers )
83  return false;
84 
85  if( m_angle != other.m_angle )
86  return false;
87 
88  return true;
89  }
90 
91  bool isSMD() const
92  {
93  return m_type == PAD_ATTRIB::SMD;
94  }
95 
97  {
98  for( auto l : LSET::AllCuMask().Seq() )
99  {
100  if( m_layers[l] )
101  return l;
102  }
103  return F_Cu;
104  }
105 
106  void SetId( int id )
107  {
108  m_id = id;
109  }
110 
111  int GetId() const
112  {
113  return m_id;
114  }
115 
117  {
118  switch( m_shape )
119  {
120  case PAD_SHAPE::CIRCLE:
121  case PAD_SHAPE::OVAL:
123  case PAD_SHAPE::RECT: return true;
124  default: return false;
125  }
126  }
127 
128  bool isEmpty() const
129  {
130  LSET layerMask = LSET::AllCuMask() & m_board->GetEnabledLayers();
131  LSET outLayers = m_layers & layerMask;
132 
133  return outLayers.none();
134  }
135 
136 private:
138  int m_id;
139  int m_drill;
141  int m_sx, m_sy;
142  double m_angle;
145 };
146 
147 
149 {
150 public:
152  {
153  }
154 
156 
157  virtual bool Run() override;
158 
159 private:
161  {
162  for( HYPERLYNX_PAD_STACK* p : m_padStacks )
163  {
164  if( *p == stack )
165  return p;
166  }
167 
168  stack.SetId( m_padStacks.size() );
169  m_padStacks.push_back( new HYPERLYNX_PAD_STACK( stack ) );
170 
171  return m_padStacks.back();
172  }
173 
174  const std::string formatPadShape( const HYPERLYNX_PAD_STACK& aStack )
175  {
176  int shapeId = 0;
177  char buf[1024];
178 
179  switch( aStack.m_shape )
180  {
181  case PAD_SHAPE::CIRCLE:
182  case PAD_SHAPE::OVAL: shapeId = 0; break;
183  case PAD_SHAPE::ROUNDRECT: shapeId = 2; break;
184  case PAD_SHAPE::RECT: shapeId = 1; break;
185  default:
186  shapeId = 0;
187 
188  if( m_reporter )
189  {
190  m_reporter->Report( _( "File contains pad shapes that are not supported by the "
191  "Hyperlynx exporter (supported shapes are oval, rectangle "
192  "and circle)." ),
194  m_reporter->Report( _( "They have been exported as oval pads." ),
196  }
197  break;
198  }
199 
200  snprintf( buf, sizeof( buf ), "%d, %.9f, %.9f, %.1f, M", shapeId,
201  iu2hyp( aStack.m_sx ),
202  iu2hyp( aStack.m_sy ),
203  aStack.m_angle );
204 
205  return buf;
206  }
207 
208  bool generateHeaders();
209  bool writeBoardInfo();
210  bool writeStackupInfo();
211  bool writeDevices();
212  bool writePadStacks();
213  bool writeNets();
214  bool writeNetObjects( const std::vector<BOARD_ITEM*>& aObjects );
215 
216 
218 
219  const std::vector<BOARD_ITEM*> collectNetObjects( int netcode );
220 
221  std::vector<HYPERLYNX_PAD_STACK*> m_padStacks;
222  std::map<BOARD_ITEM*, HYPERLYNX_PAD_STACK*> m_padMap;
223 
224 
225  std::shared_ptr<FILE_OUTPUTFORMATTER> m_out;
226  int m_polyId;
227 };
228 
229 
231 {
232  m_board = aBoard;
233  m_sx = aPad->GetSize().x;
234  m_sy = aPad->GetSize().y;
235  m_angle = 180.0 - ( aPad->GetOrientation() / 10.0 );
236 
237  if( m_angle < 0.0 )
238  {
239  m_angle += 360.0;
240  }
241 
242  m_layers = aPad->GetLayerSet();
243  m_drill = aPad->GetDrillSize().x;
244  m_shape = aPad->GetShape();
246  m_id = 0;
247 }
248 
249 
251 {
252  m_board = aBoard;
253  m_sx = aVia->GetWidth();
254  m_sy = aVia->GetWidth();
255  m_angle = 0;
257  m_drill = aVia->GetDrillValue();
260  m_id = 0;
261 }
262 
263 
265 {
266  m_out->Print( 0, "{VERSION=2.14}\n" );
267  m_out->Print( 0, "{UNITS=ENGLISH LENGTH}\n\n" );
268  return true;
269 }
270 
271 
273 {
274  LSET layerMask = LSET::AllCuMask() & m_board->GetEnabledLayers();
275  LSET outLayers = aStack.m_layers & layerMask;
276 
277  if( outLayers.none() )
278  return;
279 
280  m_out->Print( 0, "{PADSTACK=%d, %.9f\n", aStack.m_id, iu2hyp( aStack.m_drill ) );
281 
282  if( outLayers == layerMask )
283  {
284  m_out->Print( 1, "(\"%s\", %s)\n", "MDEF", formatPadShape( aStack ).c_str() );
285  }
286  else
287  {
288  for( PCB_LAYER_ID l : outLayers.Seq() )
289  {
290  m_out->Print( 1, "(\"%s\", %s)\n", (const char*) m_board->GetLayerName( l ).c_str(),
291  formatPadShape( aStack ).c_str() );
292  }
293  }
294 
295  m_out->Print( 0, "}\n\n" );
296 }
297 
298 
300 {
301  SHAPE_POLY_SET outlines;
302 
303  m_out->Print( 0, "{BOARD \"%s\"\n", (const char*) m_board->GetFileName().c_str() );
304 
305  if( !m_board->GetBoardPolygonOutlines( outlines ) )
306  {
307  wxLogError( _( "Board outline is malformed. Run DRC for a full analysis." ) );
308  return false;
309  }
310 
311  for( int o = 0; o < outlines.OutlineCount(); o++ )
312  {
313  const SHAPE_LINE_CHAIN& outl = outlines.COutline( o );
314 
315  for( int i = 0; i < outl.SegmentCount(); i++ )
316  {
317  const auto& s = outl.CSegment( i );
318  m_out->Print( 1, "(PERIMETER_SEGMENT X1=%.9f Y1=%.9f X2=%.9f Y2=%.9f)\n",
319  iu2hyp( s.A.x ), iu2hyp( s.A.y ), iu2hyp( s.B.x ), iu2hyp( s.B.y ) );
320  }
321  }
322 
323  m_out->Print( 0, "}\n\n" );
324 
325  return true;
326 }
327 
328 
330 {
331  /* Format:
332  * {STACKUP
333  * (SIGNAL T=thickness [P=plating_thickness] [C=constant] L=layer_name [M=material_name]) [comment]
334  * (DIELECTRIC T=thickness [C=constant] [L=layer_name] [M=material_name]) [comment]
335  * }
336  * name length is <= 20 chars
337  */
338 
340 
341  // Get the board physical stackup structure
343 
344  m_out->Print( 0, "{STACKUP\n" );
345 
346  wxString layer_name; // The last copper layer name used in stackup
347 
348  for( BOARD_STACKUP_ITEM* item: stackup.GetList() )
349  {
350  if( item->GetType() == BS_ITEM_TYPE_COPPER )
351  {
352  layer_name = m_board->GetLayerName( item->GetBrdLayerId() );
353  int plating_thickness = 0;
354  double resistivity = 1.724e-8; // Good for copper
355  m_out->Print( 1, "(SIGNAL T=%g P=%g C=%g L=\"%.20s\" M=COPPER)\n",
356  iu2hyp( item->GetThickness( 0 ) ),
357  iu2hyp( plating_thickness ),
358  resistivity,
359  TO_UTF8( layer_name ) );
360  }
361  else if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
362  {
363  if( item->GetSublayersCount() < 2 )
364  {
365  m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"DE_%.17s\" M=\"%.20s\")\n",
366  iu2hyp( item->GetThickness( 0 ) ),
367  item->GetEpsilonR( 0 ),
368  TO_UTF8( layer_name ),
369  TO_UTF8( item->GetMaterial( 0 ) ) );
370  }
371  else for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
372  {
373  m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"DE%d_%.16s\" M=\"%.20s\")\n",
374  iu2hyp( item->GetThickness( idx ) ),
375  item->GetEpsilonR( idx ),
376  idx, TO_UTF8( layer_name ),
377  TO_UTF8( item->GetMaterial( idx ) ) );
378  }
379  }
380  }
381 
382  m_out->Print( 0, "}\n\n" );
383 
384  return true;
385 }
386 
387 
389 {
390  m_out->Print( 0, "{DEVICES\n" );
391 
392  for( FOOTPRINT* footprint : m_board->Footprints() )
393  {
394  wxString ref = footprint->GetReference();
395  wxString layerName = m_board->GetLayerName( footprint->GetLayer() );
396 
397  if( ref.IsEmpty() )
398  ref = "EMPTY";
399 
400  m_out->Print( 1, "(? REF=\"%s\" L=\"%s\")\n", (const char*) ref.c_str(),
401  (const char*) layerName.c_str() );
402  }
403  m_out->Print( 0, "}\n\n" );
404 
405  return true;
406 }
407 
408 
410 {
411  for( FOOTPRINT* footprint : m_board->Footprints() )
412  {
413  for( PAD* pad : footprint->Pads() )
414  {
416  m_padMap[pad] = ps;
417  }
418  }
419 
420  for( PCB_TRACK* track : m_board->Tracks() )
421  {
422  if( PCB_VIA* via = dyn_cast<PCB_VIA*>( track ) )
423  {
425  m_padMap[via] = ps;
426  }
427  }
428 
429  for( HYPERLYNX_PAD_STACK* pstack : m_padStacks )
430  writeSinglePadStack( *pstack );
431 
432  return true;
433 }
434 
435 
436 bool HYPERLYNX_EXPORTER::writeNetObjects( const std::vector<BOARD_ITEM*>& aObjects )
437 {
438  for( BOARD_ITEM* item : aObjects )
439  {
440  if( PAD* pad = dyn_cast<PAD*>( item ) )
441  {
442  auto pstackIter = m_padMap.find( pad );
443 
444  if( pstackIter != m_padMap.end() )
445  {
446  wxString ref = pad->GetParent()->GetReference();
447 
448  if( ref.IsEmpty() )
449  ref = "EMPTY";
450 
451  wxString padName = pad->GetNumber();
452 
453  if( padName.IsEmpty() )
454  padName = "1";
455 
456 
457  m_out->Print( 1, "(PIN X=%.10f Y=%.10f R=\"%s.%s\" P=%d)\n",
458  iu2hyp( pad->GetPosition().x ), iu2hyp( pad->GetPosition().y ),
459  (const char*) ref.c_str(), (const char*) padName.c_str(),
460  pstackIter->second->GetId() );
461  }
462  }
463  else if( PCB_VIA* via = dyn_cast<PCB_VIA*>( item ) )
464  {
465  auto pstackIter = m_padMap.find( via );
466 
467  if( pstackIter != m_padMap.end() )
468  {
469  m_out->Print( 1, "(VIA X=%.10f Y=%.10f P=%d)\n", iu2hyp( via->GetPosition().x ),
470  iu2hyp( via->GetPosition().y ), pstackIter->second->GetId() );
471  }
472  }
473  else if( PCB_TRACK* track = dyn_cast<PCB_TRACK*>( item ) )
474  {
475  const wxString layerName = m_board->GetLayerName( track->GetLayer() );
476 
477  m_out->Print( 1, "(SEG X1=%.10f Y1=%.10f X2=%.10f Y2=%.10f W=%.10f L=\"%s\")\n",
478  iu2hyp( track->GetStart().x ), iu2hyp( track->GetStart().y ),
479  iu2hyp( track->GetEnd().x ), iu2hyp( track->GetEnd().y ),
480  iu2hyp( track->GetWidth() ), (const char*) layerName.c_str() );
481  }
482  else if( ZONE* zone = dyn_cast<ZONE*>( item ) )
483  {
484  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
485  {
486  const wxString layerName = m_board->GetLayerName( layer );
487  SHAPE_POLY_SET filledShape = zone->GetFilledPolysList( layer );
488 
489  filledShape.Simplify( SHAPE_POLY_SET::PM_FAST );
490 
491  for( int i = 0; i < filledShape.OutlineCount(); i++ )
492  {
493  const SHAPE_LINE_CHAIN& outl = filledShape.COutline( i );
494 
495  auto p0 = outl.CPoint( 0 );
496  m_out->Print( 1, "{POLYGON T=POUR L=\"%s\" ID=%d X=%.10f Y=%.10f\n",
497  (const char*) layerName.c_str(), m_polyId, iu2hyp( p0.x ),
498  iu2hyp( p0.y ) );
499 
500  for( int v = 0; v < outl.PointCount(); v++ )
501  {
502  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n", iu2hyp( outl.CPoint( v ).x ),
503  iu2hyp( outl.CPoint( v ).y ) );
504  }
505 
506  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n", iu2hyp( p0.x ), iu2hyp( p0.y ) );
507  m_out->Print( 1, "}\n" );
508 
509  for( int h = 0; h < filledShape.HoleCount( i ); h++ )
510  {
511  const SHAPE_LINE_CHAIN& holeShape = filledShape.CHole( i, h );
512  VECTOR2I ph0 = holeShape.CPoint( 0 );
513 
514  m_out->Print( 1, "{POLYVOID ID=%d X=%.10f Y=%.10f\n", m_polyId,
515  iu2hyp( ph0.x ), iu2hyp( ph0.y ) );
516 
517  for( int v = 0; v < holeShape.PointCount(); v++ )
518  {
519  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
520  iu2hyp( holeShape.CPoint( v ).x ),
521  iu2hyp( holeShape.CPoint( v ).y ) );
522  }
523 
524  m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
525  iu2hyp( ph0.x ), iu2hyp( ph0.y ) );
526  m_out->Print( 1, "}\n" );
527  }
528 
529  m_polyId++;
530  }
531  }
532  }
533  }
534 
535  return true;
536 }
537 
538 
539 const std::vector<BOARD_ITEM*> HYPERLYNX_EXPORTER::collectNetObjects( int netcode )
540 {
541  std::vector<BOARD_ITEM*> rv;
542 
543  auto check =
544  [&]( BOARD_CONNECTED_ITEM* item ) -> bool
545  {
546  if( ( item->GetLayerSet() & LSET::AllCuMask() ).none() )
547  return false;
548 
549  if( item->GetNetCode() == netcode || ( netcode < 0 && item->GetNetCode() <= 0 ) )
550  return true;
551 
552  return false;
553  };
554 
555  for( FOOTPRINT* footprint : m_board->Footprints() )
556  {
557  for( PAD* pad : footprint->Pads() )
558  {
559  if( check( pad ) )
560  rv.push_back( pad );
561  }
562  }
563 
564  for( PCB_TRACK* item : m_board->Tracks() )
565  {
566  if( check( item ) )
567  rv.push_back( item );
568  }
569 
570  for( ZONE* zone : m_board->Zones() )
571  {
572  if( check( zone ) )
573  rv.push_back( zone );
574  }
575 
576  return rv;
577 }
578 
579 
581 {
582  m_polyId = 1;
583 
584  for( const auto netInfo : m_board->GetNetInfo() )
585  {
586  int netcode = netInfo->GetNetCode();
587  bool isNullNet = netInfo->GetNetCode() <= 0 || netInfo->GetNetname().IsEmpty();
588 
589  if( isNullNet )
590  continue;
591 
592  auto netObjects = collectNetObjects( netcode );
593 
594  if( netObjects.size() )
595  {
596  m_out->Print( 0, "{NET=\"%s\"\n", (const char*) netInfo->GetNetname().c_str() );
597  writeNetObjects( netObjects );
598  m_out->Print( 0, "}\n\n" );
599  }
600  }
601 
602  auto nullNetObjects = collectNetObjects( -1 );
603 
604  int idx = 0;
605 
606  for( auto item : nullNetObjects )
607  {
608  m_out->Print( 0, "{NET=\"EmptyNet%d\"\n", idx );
609  writeNetObjects( { item } );
610  m_out->Print( 0, "}\n\n" );
611  idx++;
612  }
613 
614  return true;
615 }
616 
617 
619 {
620  LOCALE_IO toggle; // toggles on, then off, the C locale.
621 
622  try
623  {
624  m_out.reset( new FILE_OUTPUTFORMATTER( m_outputFilePath.GetFullPath() ) );
625 
626  generateHeaders();
627  writeBoardInfo();
629  writeDevices();
630  writePadStacks();
631  writeNets();
632  }
633  catch( IO_ERROR& )
634  {
635  return false;
636  }
637 
638  return true;
639 }
640 
641 
642 bool ExportBoardToHyperlynx( BOARD* aBoard, const wxFileName& aPath )
643 {
644  HYPERLYNX_EXPORTER exporter;
645  exporter.SetBoard( aBoard );
646  exporter.SetOutputFilename( aPath );
647  return exporter.Run();
648 }
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)
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:361
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:1899
ZONES & Zones()
Definition: board.h:239
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:40
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:80
Smd pad, appears on the solder paste layer (default)
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:684
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:466
int GetWidth() const
Definition: pcb_track.h:102
int PointCount() const
Return the number of points (vertices) in this line chain.
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:228
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:589
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
std::vector< HYPERLYNX_PAD_STACK * > m_padStacks
Plated through hole pad.
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
Return a reference to a given point in the line chain.
HYPERLYNX_PAD_STACK * addPadStack(HYPERLYNX_PAD_STACK stack)
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape() DO NOT REORDER, legacy_plugin is dependent on ...
Definition: pad_shapes.h:33
const wxSize & GetDrillSize() const
Definition: pad.h:243
like PAD_PTH, but not plated
BOARD_STACKUP & GetStackupDescriptor()
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
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
Represent a set of closed polygons.
std::map< BOARD_ITEM *, HYPERLYNX_PAD_STACK * > m_padMap
FOOTPRINTS & Footprints()
Definition: board.h:233
const wxSize & GetSize() const
Definition: pad.h:233
HYPERLYNX_PAD_STACK(BOARD *aBoard, const PAD *aPad)
PAD_SHAPE GetShape() const
Definition: pad.h:170
#define _(s)
void Simplify(POLYGON_MODE aFastMode)
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
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.
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition: pad_shapes.h:79
int SegmentCount() const
Return the number of segments in this line chain.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:463
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
PCB_LAYER_ID getSMDLayer() const
void writeSinglePadStack(HYPERLYNX_PAD_STACK &aStack)
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
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)
Represent a polyline (an zero-thickness chain of connected line segments).
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:64
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Definition: layer_ids.h:70
const std::vector< BOARD_ITEM * > collectNetObjects(int netcode)
std::shared_ptr< FILE_OUTPUTFORMATTER > m_out
virtual bool Run() override
Used for text file output.
Definition: richio.h:456
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: pcb_track.cpp:193
Definition: pad.h:57
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:230
const std::string formatPadShape(const HYPERLYNX_PAD_STACK &aStack)