KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <cstdio>
22#include <vector>
23
24#include <wx/log.h>
25#include <wx/filedlg.h>
26#include <kiplatform/ui.h>
27
28#include <kiface_base.h>
29#include <macros.h>
30#include <pcb_edit_frame.h>
31#include <board.h>
33#include <board_item.h>
34#include <footprint.h>
35#include <pad.h>
36#include <pcb_track.h>
37#include <zone.h>
38#include <ki_exception.h>
39#include <locale_io.h>
40#include <reporter.h>
41#include <richio.h>
42#include <string_utils.h>
47
48
49static double iu2hyp( double iu )
50{
51 return iu / 1e9 / 0.0254;
52}
53
54
56
59{
61 int m_sx;
62 int m_sy;
63
64 bool operator==( const HYPERLYNX_PAD_SHAPE& aOther ) const = default;
65};
66
67
69{
70public:
71 friend class HYPERLYNX_EXPORTER;
72
73 HYPERLYNX_PAD_STACK( BOARD* aBoard, const PAD* aPad );
74 HYPERLYNX_PAD_STACK( BOARD* aBoard, const PCB_VIA* aVia );
76
77 bool IsThrough() const
78 {
80 }
81
82 bool operator==( const HYPERLYNX_PAD_STACK& other ) const
83 {
84 if( m_type != other.m_type )
85 return false;
86
87 if( IsThrough() && other.IsThrough() && m_drill != other.m_drill )
88 return false;
89
90 if( m_shapes != other.m_shapes )
91 return false;
92
93 if( m_layers != other.m_layers )
94 return false;
95
96 if( m_angle != other.m_angle )
97 return false;
98
99 return true;
100 }
101
102 void SetId( int id )
103 {
104 m_id = id;
105 }
106
107 int GetId() const
108 {
109 return m_id;
110 }
111
112 bool IsEmpty() const
113 {
114 LSET outLayers = m_layers & LSET::AllCuMask( m_board->GetCopperLayerCount() );
115
116 return outLayers.none();
117 }
118
119private:
121 int m_id;
123 double m_angle;
126
128 std::map<PCB_LAYER_ID, HYPERLYNX_PAD_SHAPE> m_shapes;
129};
130
131
133{
134public:
136 {
137 }
138
140
141 virtual bool Run() override;
142
143private:
145 {
147 {
148 if( *p == stack )
149 return p;
150 }
151
152 stack.SetId( m_padStacks.size() );
153 m_padStacks.push_back( new HYPERLYNX_PAD_STACK( stack ) );
154
155 return m_padStacks.back();
156 }
157
158 const std::string formatPadShape( const HYPERLYNX_PAD_SHAPE& aShape, double aAngle )
159 {
160 int shapeId = 0;
161 char buf[1024];
162
163 switch( aShape.m_shape )
164 {
166 case PAD_SHAPE::OVAL:
167 shapeId = 0;
168 break;
169
171 shapeId = 2;
172 break;
173
175 shapeId = 1;
176 break;
177
178 default:
179 if( m_reporter )
180 {
181 m_reporter->Report( _( "File contains pad shapes that are not supported by the "
182 "Hyperlynx exporter (supported shapes are oval, rectangle, "
183 "rounded rectangle, and circle)." ),
185 m_reporter->Report( _( "They have been exported as oval pads." ),
187 }
188
189 shapeId = 0;
190 break;
191 }
192
193 snprintf( buf, sizeof( buf ), "%d, %.9f, %.9f, %.1f, M",
194 shapeId,
195 iu2hyp( aShape.m_sx ),
196 iu2hyp( aShape.m_sy ),
197 aAngle );
198
199 return buf;
200 }
201
202 bool generateHeaders();
203 bool writeBoardInfo();
204 bool writeStackupInfo();
205 bool writeDevices();
206 bool writePadStacks();
207 bool writeNets();
208 bool writeNetObjects( const std::vector<BOARD_ITEM*>& aObjects );
209
210
212
213 const std::vector<BOARD_ITEM*> collectNetObjects( int netcode );
214
215private:
216 std::vector<HYPERLYNX_PAD_STACK*> m_padStacks;
217 std::map<BOARD_ITEM*, HYPERLYNX_PAD_STACK*> m_padMap;
218
219 std::shared_ptr<FILE_OUTPUTFORMATTER> m_out;
221};
222
223
225{
226 m_board = aBoard;
227 m_angle = 180.0 - aPad->GetOrientation().AsDegrees();
228
229 if( m_angle < 0.0 )
230 m_angle += 360.0;
231
232 m_layers = aPad->GetLayerSet();
233 m_drill = aPad->GetDrillSize().x;
235 m_id = 0;
236
237 LSET copperLayers = m_layers & LSET::AllCuMask( aBoard->GetCopperLayerCount() );
238
239 for( PCB_LAYER_ID layer : copperLayers.Seq() )
240 {
241 PCB_LAYER_ID padLayer = aPad->Padstack().EffectiveLayerFor( layer );
242
243 m_shapes[layer] = { aPad->GetShape( padLayer ), aPad->GetSize( padLayer ).x,
244 aPad->GetSize( padLayer ).y };
245 }
246}
247
248
250{
251 m_board = aBoard;
252 m_angle = 0;
253 m_layers = aVia->GetLayerSet();
254 m_drill = aVia->GetDrillValue();
256 m_id = 0;
257
258 LSET copperLayers = m_layers & LSET::AllCuMask( aBoard->GetCopperLayerCount() );
259
260 for( PCB_LAYER_ID layer : copperLayers.Seq() )
261 {
262 int width = aVia->GetWidth( aVia->Padstack().EffectiveLayerFor( layer ) );
263
264 m_shapes[layer] = { PAD_SHAPE::CIRCLE, width, width };
265 }
266}
267
268
270{
271 m_out->Print( 0, "{VERSION=2.14}\n" );
272 m_out->Print( 0, "{UNITS=ENGLISH LENGTH}\n\n" );
273 return true;
274}
275
276
278{
279 LSET layerMask = LSET::AllCuMask( m_board->GetCopperLayerCount() );
280 LSET outLayers = aStack.m_layers & layerMask;
281
282 if( outLayers.none() )
283 return;
284
285 const HYPERLYNX_PAD_SHAPE& firstShape = aStack.m_shapes.begin()->second;
286
287 bool uniform = std::all_of( aStack.m_shapes.begin(), aStack.m_shapes.end(),
288 [&]( const auto& aEntry )
289 {
290 return aEntry.second == firstShape;
291 } );
292
293 // The spec requires the drill parameter to be absent, not zero, on a padstack with no hole
294 if( aStack.m_drill > 0 )
295 m_out->Print( 0, "{PADSTACK=%d, %.9f\n", aStack.m_id, iu2hyp( aStack.m_drill ) );
296 else
297 m_out->Print( 0, "{PADSTACK=%d\n", aStack.m_id );
298
299 if( outLayers == layerMask && uniform )
300 {
301 m_out->Print( 1, "(\"MDEF\", %s)\n", formatPadShape( firstShape, aStack.m_angle ).c_str() );
302 }
303 else
304 {
305 for( PCB_LAYER_ID l : outLayers.Seq() )
306 {
307 m_out->Print( 1, "(\"%s\", %s)\n",
308 (const char*) m_board->GetLayerName( l ).c_str(),
309 formatPadShape( aStack.m_shapes.at( l ), aStack.m_angle ).c_str() );
310 }
311 }
312
313 m_out->Print( 0, "}\n\n" );
314}
315
316
318{
319 SHAPE_POLY_SET outlines;
320
321 m_out->Print( 0, "{BOARD \"%s\"\n", (const char*) m_board->GetFileName().c_str() );
322
323 if( !m_board->GetBoardPolygonOutlines( outlines, false ) )
324 {
325 wxLogError( _( "Board outline is malformed. Run DRC for a full analysis." ) );
326 return false;
327 }
328
329 for( int o = 0; o < outlines.OutlineCount(); o++ )
330 {
331 const SHAPE_LINE_CHAIN& outl = outlines.COutline( o );
332
333 for( int i = 0; i < outl.SegmentCount(); i++ )
334 {
335 const SEG& s = outl.CSegment( i );
336 m_out->Print( 1, "(PERIMETER_SEGMENT X1=%.9f Y1=%.9f X2=%.9f Y2=%.9f)\n",
337 iu2hyp( s.A.x ),
338 iu2hyp( -s.A.y ),
339 iu2hyp( s.B.x ),
340 iu2hyp( -s.B.y ) );
341 }
342 }
343
344 m_out->Print( 0, "}\n\n" );
345
346 return true;
347}
348
349
351{
352 /* Format:
353 * {STACKUP
354 * (SIGNAL T=thickness [P=plating_thickness] [C=resistivity] L=layer_name [M=material_name])
355 * (DIELECTRIC T=thickness [C=dielectric_constant] [L=layer_name] [M=material_name])
356 * }
357 * C parameter: bulk resistivity (ohm-m) for SIGNAL, epsilon_r for DIELECTRIC
358 * Layer name length is <= 20 chars
359 */
360
361 LSEQ layers = m_board->GetDesignSettings().GetEnabledLayers().CuStack();
362
363 // Get the board physical stackup structure
364 const BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor();
365
366 m_out->Print( 0, "{STACKUP\n" );
367
368 wxString layer_name; // The last copper layer name used in stackup
369
370 for( BOARD_STACKUP_ITEM* item: stackup.GetList() )
371 {
372 if( item->GetType() == BS_ITEM_TYPE_COPPER )
373 {
374 layer_name = m_board->GetLayerName( item->GetBrdLayerId() );
375 int plating_thickness = 0;
376 double resistivity = 1.724e-8; // Copper bulk resistivity in ohm-meters
377 m_out->Print( 1, "(SIGNAL T=%g P=%g C=%g L=\"%.20s\" M=COPPER)\n",
378 iu2hyp( item->GetThickness( 0 ) ),
379 iu2hyp( plating_thickness ),
380 resistivity,
381 TO_UTF8( layer_name ) );
382 }
383 else if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
384 {
385 if( item->GetSublayersCount() < 2 )
386 {
387 m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"DE_%.17s\" M=\"%.20s\")\n",
388 iu2hyp( item->GetThickness( 0 ) ),
389 item->GetEpsilonR( 0 ),
390 TO_UTF8( layer_name ),
391 TO_UTF8( item->GetMaterial( 0 ) ) );
392 }
393 else for( int idx = 0; idx < item->GetSublayersCount(); idx++ )
394 {
395 m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"DE%d_%.16s\" M=\"%.20s\")\n",
396 iu2hyp( item->GetThickness( idx ) ),
397 item->GetEpsilonR( idx ),
398 idx,
399 TO_UTF8( layer_name ),
400 TO_UTF8( item->GetMaterial( idx ) ) );
401 }
402 }
403 else if( item->GetType() == BS_ITEM_TYPE_SOLDERMASK )
404 {
405 // Soldermask uses its KiCad layer name directly (e.g., "F.Mask") rather than
406 // a constructed name like core dielectrics, since these names are already unique.
407 wxString maskLayerName = m_board->GetLayerName( item->GetBrdLayerId() );
408 wxString material = item->GetMaterial( 0 );
409
410 if( !IsPrmSpecified( material ) )
411 material = wxT( "Solder Mask" );
412
413 m_out->Print( 1, "(DIELECTRIC T=%g C=%g L=\"%.20s\" M=\"%.20s\")\n",
414 iu2hyp( item->GetThickness( 0 ) ),
415 item->GetEpsilonR( 0 ),
416 TO_UTF8( maskLayerName ),
417 TO_UTF8( material ) );
418 }
419 }
420
421 m_out->Print( 0, "}\n\n" );
422
423 return true;
424}
425
426
428{
429 m_out->Print( 0, "{DEVICES\n" );
430
431 for( FOOTPRINT* footprint : m_board->Footprints() )
432 {
433 wxString ref = footprint->GetReference();
434 wxString layerName = m_board->GetLayerName( footprint->GetLayer() );
435
436 if( ref.IsEmpty() )
437 ref = wxT( "EMPTY" );
438
439 m_out->Print( 1, "(? REF=\"%s\" L=\"%s\")\n",
440 (const char*) ref.c_str(),
441 (const char*) layerName.c_str() );
442 }
443 m_out->Print( 0, "}\n\n" );
444
445 return true;
446}
447
448
450{
451 for( FOOTPRINT* footprint : m_board->Footprints() )
452 {
453 for( PAD* pad : footprint->Pads() )
454 {
456 m_padMap[pad] = ps;
457 }
458 }
459
460 for( PCB_TRACK* track : m_board->Tracks() )
461 {
462 if( PCB_VIA* via = dyn_cast<PCB_VIA*>( track ) )
463 {
465 m_padMap[via] = ps;
466 }
467 }
468
469 for( HYPERLYNX_PAD_STACK* pstack : m_padStacks )
470 writeSinglePadStack( *pstack );
471
472 return true;
473}
474
475
476bool HYPERLYNX_EXPORTER::writeNetObjects( const std::vector<BOARD_ITEM*>& aObjects )
477{
478 for( BOARD_ITEM* item : aObjects )
479 {
480 if( PAD* pad = dyn_cast<PAD*>( item ) )
481 {
482 auto pstackIter = m_padMap.find( pad );
483
484 if( pstackIter != m_padMap.end() )
485 {
486 wxString ref = pad->GetParentFootprint()->GetReference();
487
488 if( ref.IsEmpty() )
489 ref = wxT( "EMPTY" );
490
491 wxString padName = pad->GetNumber();
492
493 if( padName.IsEmpty() )
494 padName = wxT( "1" );
495
496
497 m_out->Print( 1, "(PIN X=%.10f Y=%.10f R=\"%s.%s\" P=%d)\n",
498 iu2hyp( pad->GetPosition().x ),
499 iu2hyp( -pad->GetPosition().y ),
500 (const char*) ref.c_str(),
501 (const char*) padName.c_str(),
502 pstackIter->second->GetId() );
503 }
504 }
505 else if( PCB_VIA* via = dyn_cast<PCB_VIA*>( item ) )
506 {
507 auto pstackIter = m_padMap.find( via );
508
509 if( pstackIter != m_padMap.end() )
510 {
511 m_out->Print( 1, "(VIA X=%.10f Y=%.10f P=%d)\n",
512 iu2hyp( via->GetPosition().x ),
513 iu2hyp( -via->GetPosition().y ),
514 pstackIter->second->GetId() );
515 }
516 }
517 else if( PCB_TRACK* track = dyn_cast<PCB_TRACK*>( item ) )
518 {
519 const wxString layerName = m_board->GetLayerName( track->GetLayer() );
520
521 m_out->Print( 1, "(SEG X1=%.10f Y1=%.10f X2=%.10f Y2=%.10f W=%.10f L=\"%s\")\n",
522 iu2hyp( track->GetStart().x ),
523 iu2hyp( -track->GetStart().y ),
524 iu2hyp( track->GetEnd().x ),
525 iu2hyp( -track->GetEnd().y ),
526 iu2hyp( track->GetWidth() ),
527 (const char*) layerName.c_str() );
528 }
529 else if( PCB_ARC* arc = dyn_cast<PCB_ARC*>( item ) )
530 {
531 const wxString layerName = m_board->GetLayerName( arc->GetLayer() );
532 VECTOR2I start = arc->GetStart();
533 VECTOR2I end = arc->GetEnd();
534
535 if( !arc->IsCCW() )
536 std::swap( start, end );
537
538 m_out->Print( 1, "(ARC X1=%.10f Y1=%.10f X2=%.10f Y2=%.10f XC=%.10f YC=%.10f R=%.10f W=%.10f L=\"%s\")\n",
539 iu2hyp( start.x ),
540 iu2hyp( -start.y ),
541 iu2hyp( end.x ),
542 iu2hyp( -end.y ),
543 iu2hyp( arc->GetCenter().x ),
544 iu2hyp( -arc->GetCenter().y ),
545 iu2hyp( arc->GetRadius() ),
546 iu2hyp( arc->GetWidth() ),
547 (const char*) layerName.c_str() );
548 }
549 else if( ZONE* zone = dyn_cast<ZONE*>( item ) )
550 {
551 for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
552 {
553 const wxString layerName = m_board->GetLayerName( layer );
554 SHAPE_POLY_SET fill = zone->GetFilledPolysList( layer )->CloneDropTriangulation();
555
556 fill.Simplify();
557
558 for( int i = 0; i < fill.OutlineCount(); i++ )
559 {
560 const SHAPE_LINE_CHAIN& outl = fill.COutline( i );
561 const VECTOR2I p0 = outl.CPoint( 0 );
562
563 m_out->Print( 1, "{POLYGON T=POUR L=\"%s\" ID=%d X=%.10f Y=%.10f\n",
564 (const char*) layerName.c_str(),
565 m_polyId,
566 iu2hyp( p0.x ),
567 iu2hyp( -p0.y ) );
568
569 for( int v = 0; v < outl.PointCount(); v++ )
570 {
571 m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
572 iu2hyp( outl.CPoint( v ).x ),
573 iu2hyp( -outl.CPoint( v ).y ) );
574 }
575
576 m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n", iu2hyp( p0.x ), iu2hyp( -p0.y ) );
577 m_out->Print( 1, "}\n" );
578
579 for( int h = 0; h < fill.HoleCount( i ); h++ )
580 {
581 const SHAPE_LINE_CHAIN& holeShape = fill.CHole( i, h );
582 const VECTOR2I ph0 = holeShape.CPoint( 0 );
583
584 m_out->Print( 1, "{POLYVOID ID=%d X=%.10f Y=%.10f\n",
585 m_polyId,
586 iu2hyp( ph0.x ),
587 iu2hyp( -ph0.y ) );
588
589 for( int v = 0; v < holeShape.PointCount(); v++ )
590 {
591 m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
592 iu2hyp( holeShape.CPoint( v ).x ),
593 iu2hyp( -holeShape.CPoint( v ).y ) );
594 }
595
596 m_out->Print( 2, "(LINE X=%.10f Y=%.10f)\n",
597 iu2hyp( ph0.x ),
598 iu2hyp( -ph0.y ) );
599 m_out->Print( 1, "}\n" );
600 }
601
602 m_polyId++;
603 }
604 }
605 }
606 }
607
608 return true;
609}
610
611
612const std::vector<BOARD_ITEM*> HYPERLYNX_EXPORTER::collectNetObjects( int netcode )
613{
614 std::vector<BOARD_ITEM*> rv;
615
616 auto check =
617 [&]( BOARD_CONNECTED_ITEM* item ) -> bool
618 {
619 if( ( item->GetLayerSet() & LSET::AllCuMask() ).none() )
620 return false;
621
622 if( item->GetNetCode() == netcode || ( netcode < 0 && item->GetNetCode() <= 0 ) )
623 return true;
624
625 return false;
626 };
627
628 for( FOOTPRINT* footprint : m_board->Footprints() )
629 {
630 for( PAD* pad : footprint->Pads() )
631 {
632 if( check( pad ) )
633 rv.push_back( pad );
634 }
635 }
636
637 for( PCB_TRACK* item : m_board->Tracks() )
638 {
639 if( check( item ) )
640 rv.push_back( item );
641 }
642
643 for( ZONE* zone : m_board->Zones() )
644 {
645 if( check( zone ) )
646 rv.push_back( zone );
647 }
648
649 return rv;
650}
651
652
654{
655 m_polyId = 1;
656
657 for( const NETINFO_ITEM* netInfo : m_board->GetNetInfo() )
658 {
659 int netcode = netInfo->GetNetCode();
660 bool isNullNet = netInfo->GetNetCode() <= 0 || netInfo->GetNetname().IsEmpty();
661
662 if( isNullNet )
663 continue;
664
665 const std::vector<BOARD_ITEM*> netObjects = collectNetObjects( netcode );
666
667 if( netObjects.size() )
668 {
669 m_out->Print( 0, "{NET=\"%s\"\n", (const char*) netInfo->GetNetname().c_str() );
670 writeNetObjects( netObjects );
671 m_out->Print( 0, "}\n\n" );
672 }
673 }
674
675 const std::vector<BOARD_ITEM*> nullNetObjects = collectNetObjects( -1 );
676
677 int idx = 0;
678
679 for( BOARD_ITEM* item : nullNetObjects )
680 {
681 m_out->Print( 0, "{NET=\"EmptyNet%d\"\n", idx );
682 writeNetObjects( { item } );
683 m_out->Print( 0, "}\n\n" );
684 idx++;
685 }
686
687 return true;
688}
689
690
692{
693 LOCALE_IO toggle; // toggles on, then off, the C locale.
694
695 try
696 {
697 m_out.reset( new FILE_OUTPUTFORMATTER( m_outputFilePath.GetFullPath() ) );
698
702 writeDevices();
704 writeNets();
705
706 m_out->Finish();
707 }
708 catch( IO_ERROR& )
709 {
710 return false;
711 }
712
713 return true;
714}
715
716
717bool ExportBoardToHyperlynxFile( BOARD* aBoard, const wxString& aFullFilename )
718{
719 HYPERLYNX_EXPORTER exporter;
720 exporter.SetBoard( aBoard );
721 exporter.SetOutputFilename( wxFileName( aFullFilename ) );
722
723 return exporter.Run();
724}
725
726
728{
729 wxString wildcard = wxT( "*.hyp" );
730 BOARD* board = m_frame->GetBoard();
731 wxFileName fn = board->GetFileName();
732
733 fn.SetExt( wxT("hyp") );
734
735 wxFileDialog dlg( m_frame, _( "Export Hyperlynx Layout" ), fn.GetPath(), fn.GetFullName(),
736 wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
737
739
740 if( dlg.ShowModal() != wxID_OK )
741 return 0;
742
743 fn = dlg.GetPath();
744
745 // always enforce filename extension, user may not have entered it.
746 fn.SetExt( wxT( "hyp" ) );
747
748 ExportBoardToHyperlynxFile( board, fn.GetFullPath() );
749
750 return 0;
751}
bool IsPrmSpecified(const wxString &aPrmValue)
@ BS_ITEM_TYPE_COPPER
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERMASK
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
int ExportHyperlynx(const TOOL_EVENT &aEvent)
void SetOutputFilename(const wxFileName &aPath)
void SetBoard(BOARD *aBoard)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Manage one layer needed to make a physical board.
Manage layers needed to make a physical board.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
int GetCopperLayerCount() const
Definition board.cpp:1131
double AsDegrees() const
Definition eda_angle.h:116
Used for text file output.
Definition richio.h:483
virtual bool Run() override
void writeSinglePadStack(HYPERLYNX_PAD_STACK &aStack)
const std::string formatPadShape(const HYPERLYNX_PAD_SHAPE &aShape, double aAngle)
std::vector< HYPERLYNX_PAD_STACK * > m_padStacks
std::map< BOARD_ITEM *, HYPERLYNX_PAD_STACK * > m_padMap
bool writeNetObjects(const std::vector< BOARD_ITEM * > &aObjects)
HYPERLYNX_PAD_STACK * addPadStack(HYPERLYNX_PAD_STACK stack)
std::shared_ptr< FILE_OUTPUTFORMATTER > m_out
const std::vector< BOARD_ITEM * > collectNetObjects(int netcode)
std::map< PCB_LAYER_ID, HYPERLYNX_PAD_SHAPE > m_shapes
Copper geometry per board copper layer this padstack is present on.
friend class HYPERLYNX_EXPORTER
HYPERLYNX_PAD_STACK(BOARD *aBoard, const PAD *aPad)
bool operator==(const HYPERLYNX_PAD_STACK &other) const
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition lset.cpp:309
static LSET AllCuMask(int aCuLayerCount)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition lset.cpp:595
Handle the data for a net.
Definition netinfo.h:50
PCB_LAYER_ID EffectiveLayerFor(PCB_LAYER_ID aLayer) const
Determines which geometry layer should be used for the given input layer.
Definition pad.h:61
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition pad.h:555
VECTOR2I GetDrillSize() const
Definition pad.h:318
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
Definition pad.h:205
VECTOR2I GetSize(PCB_LAYER_ID aLayer) const
Definition pad.cpp:288
const PADSTACK & Padstack() const
Definition pad.h:329
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
Definition pad.cpp:1747
BOARD * board() const
const PADSTACK & Padstack() const
Definition pcb_track.h:418
int GetWidth() const override
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
Represent a set of closed polygons.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Generic, UI-independent tool event.
Definition tool_event.h:167
Handle a list of polygons defining a copper zone.
Definition zone.h:70
#define _(s)
static double iu2hyp(double iu)
bool ExportBoardToHyperlynxFile(BOARD *aBoard, const wxString &aFullFilename)
Write aBoard to aFullFilename in Hyperlynx .hyp format.
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
This file contains miscellaneous commonly used macros and functions.
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:521
PAD_ATTRIB
The set of pad shapes, used with PAD::{Set,Get}Attribute().
Definition padstack.h:96
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:102
@ PTH
Plated through hole pad.
Definition padstack.h:97
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
Definition padstack.h:51
@ ROUNDRECT
Definition padstack.h:56
@ RECTANGLE
Definition padstack.h:53
@ RPT_SEVERITY_WARNING
@ RPT_SEVERITY_INFO
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
The copper geometry of one padstack layer, as Hyperlynx describes it in a PADSTACK entry.
bool operator==(const HYPERLYNX_PAD_SHAPE &aOther) const =default
VECTOR2I end
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:55
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683