43 else if( aId ==
B_Cu )
46 return StrPrintf(
"INNER%d", aCuCount - aId - 1 );
59 case B_Adhes: txt =
"B.Adhes";
break;
60 case F_Adhes: txt =
"F.Adhes";
break;
61 case B_Paste: txt =
"SOLDERPASTE_BOTTOM";
break;
62 case F_Paste: txt =
"SOLDERPASTE_TOP";
break;
63 case B_SilkS: txt =
"SILKSCREEN_BOTTOM";
break;
64 case F_SilkS: txt =
"SILKSCREEN_TOP";
break;
65 case B_Mask: txt =
"SOLDERMASK_BOTTOM";
break;
66 case F_Mask: txt =
"SOLDERMASK_TOP";
break;
74 case Margin: txt =
"Margin";
break;
77 case F_CrtYd: txt =
"F_CrtYd";
break;
78 case B_CrtYd: txt =
"B_CrtYd";
break;
79 case F_Fab: txt =
"F_Fab";
break;
80 case B_Fab: txt =
"B_Fab";
break;
83 wxASSERT_MSG( 0, wxT(
"aId UNEXPECTED" ) );
84 txt =
"BAD-INDEX!";
break;
95 if( 1<= aId && aId <= 14 )
104 wxString
copy( aString );
105 copy.Replace( wxT(
"\"" ), wxT(
"\\\"" ) );
123 static const wxString invalid(
"invalid" );
131 auto itName =
shapeNames.find( itShape->second );
132 wxCHECK( itName !=
shapeNames.end(), invalid );
134 return itName->second;
162 m_file = wxFopen( aFullFileName, wxT(
"wt" ) );
183 footprint->SetFlag( 0 );
185 if( footprint->GetLayer() ==
B_Cu )
187 footprint->Flip( footprint->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
188 footprint->SetFlag( 1 );
219 if( footprint->GetFlag() )
221 footprint->Flip( footprint->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
222 footprint->SetFlag( 0 );
252 fputs(
"$ARTWORKS\n",
m_file );
253 fputs(
"$ENDARTWORKS\n\n",
m_file );
262 std::vector<PAD*> padstacks;
263 std::vector<PCB_VIA*> vias;
264 std::vector<PCB_VIA*> viastacks;
266 padstacks.resize( 1 );
269 std::reverse(gc_seq.begin(), gc_seq.end());
275 fputs(
"$PADS\n",
m_file );
280 std::sort( pads.begin(), pads.end(), [](
const PAD* a,
const PAD* b )
282 return PAD::Compare( a, b ) < 0;
289 if(
PCB_VIA*
via = dyn_cast<PCB_VIA*>( track ) )
290 vias.push_back(
via );
293 std::sort( vias.begin(), vias.end(),
ViaSort );
294 vias.erase( std::unique( vias.begin(), vias.end(), [](
const PCB_VIA* a,
const PCB_VIA* b )
296 return ViaSort( a, b ) == false;
303 viastacks.push_back(
via );
304 fprintf(
m_file,
"PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
306 fmt_mask(
via->GetLayerSet() & master_layermask ).c_str(),
312 PAD* old_pad =
nullptr;
313 int pad_name_number = 0;
315 for(
unsigned i = 0; i<pads.size(); ++i )
320 pad->SetSubRatsnest( pad_name_number );
330 pad->SetSubRatsnest( pad_name_number );
332 fprintf(
m_file,
"PAD P%d",
pad->GetSubRatsnest() );
334 padstacks.push_back(
pad );
344 case PAD_SHAPE::CIRCLE:
345 fprintf(
m_file,
" ROUND %g\n",
349 fprintf(
m_file,
"CIRCLE %g %g %g\n",
355 case PAD_SHAPE::RECTANGLE:
356 fprintf(
m_file,
" RECTANGULAR %g\n",
360 fprintf(
m_file,
"RECTANGLE %g %g %g %g\n",
366 case PAD_SHAPE::ROUNDRECT:
367 case PAD_SHAPE::OVAL:
370 int radius = std::min( size.
x, size.
y ) / 2;
377 int lineX = size.
x / 2 - radius;
378 int lineY = size.
y / 2 - radius;
383 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
392 fprintf(
m_file,
"LINE %g %g %g %g\n",
400 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
410 fprintf(
m_file,
"LINE %g %g %g %g\n",
418 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
427 fprintf(
m_file,
"LINE %g %g %g %g\n"
435 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
445 fprintf(
m_file,
"LINE %g %g %g %g\n",
455 case PAD_SHAPE::TRAPEZOID:
463 poly[0] =
VECTOR2I( -dx + ddy, dy + ddx );
464 poly[1] =
VECTOR2I( dx - ddy, dy - ddx );
465 poly[2] =
VECTOR2I( dx + ddy, -dy + ddx );
466 poly[3] =
VECTOR2I( -dx - ddy, -dy - ddx );
468 for(
int cur = 0; cur < 4; ++cur )
470 int next = ( cur + 1 ) % 4;
471 fprintf(
m_file,
"LINE %g %g %g %g\n",
481 case PAD_SHAPE::CHAMFERED_RECT:
491 pad->GetOrientation(),
502 for(
int ii = 0; ii < pointCount; ii++ )
504 int next = ( ii + 1 ) % pointCount;
505 fprintf(
m_file,
"LINE %g %g %g %g\n",
516 case PAD_SHAPE::CUSTOM:
521 pad->MergePrimitivesAsPolygon(
F_Cu, &outline );
528 for(
int ii = 0; ii < pointCount; ii++ )
530 int next = ( ii + 1 ) % pointCount;
531 fprintf(
m_file,
"LINE %g %g %g %g\n",
544 fputs(
"\n$ENDPADS\n\n",
m_file );
547 fputs(
"$PADSTACKS\n",
m_file );
550 for(
unsigned i = 0; i < viastacks.size(); i++ )
554 LSET mask =
via->GetLayerSet() & master_layermask;
556 fprintf(
m_file,
"PADSTACK VIA%d.%d.%s %g\n",
563 fprintf(
m_file,
"PAD V%d.%d.%s %s 0 0\n",
575 for(
unsigned i = 1; i < padstacks.size(); i++ )
582 LSET pad_set =
pad->GetLayerSet() & master_layermask;
598 fprintf(
m_file,
"PAD P%u %s 0 0\n", i,
604 fputs(
"$ENDPADSTACKS\n\n",
m_file );
611 size_t ret = 0x11223344;
621 for(
PAD* i : aFootprint->
Pads() )
636 const char* mirror =
"0";
637 std::map<wxString, size_t> shapes;
639 fputs(
"$SHAPES\n",
m_file );
649 wxString shapeName = footprint->GetFPID().Format();
651 auto shapeIt = shapes.find( shapeName );
654 if( shapeIt != shapes.end() )
656 if( modHash != shapeIt->second )
660 wxString newShapeName;
666 newShapeName = wxString::Format( wxT(
"%s_%d" ), shapeName, suffix );
667 shapeIt = shapes.find( newShapeName );
670 while( shapeIt != shapes.end() && shapeIt->second != modHash );
672 shapeName = newShapeName;
675 if( shapeIt != shapes.end() && modHash == shapeIt->second )
686 shapes[shapeName] = modHash;
695 std::set<wxString> pins;
697 for(
PAD*
pad : footprint->Pads() )
703 pinname =
pad->GetNumber();
705 if( pinname.IsEmpty() )
706 pinname = wxT(
"none" );
711 wxString origPinname( pinname );
713 auto it = pins.find( pinname );
715 while( it != pins.end() )
717 pinname = wxString::Format( wxT(
"%s_%d" ), origPinname, suffix );
719 it = pins.find( pinname );
722 pins.insert( pinname );
725 EDA_ANGLE orient =
pad->GetOrientation() - footprint->GetOrientation();
732 "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
733 "PIN \"%s\" PAD%d %g %g %s %g %s\n",
741 fputs(
"$ENDSHAPES\n\n",
m_file );
752 fputs(
"$COMPONENTS\n",
m_file );
760 EDA_ANGLE fp_orient = footprint->GetOrientation();
762 if( footprint->GetFlag() )
774 fprintf(
m_file,
"\nCOMPONENT \"%s\"\n",
776 fprintf(
m_file,
"DEVICE \"DEV_%s\"\n",
778 fprintf(
m_file,
"PLACE %g %g\n",
779 MapXTo( footprint->GetPosition().x ),
780 MapYTo( footprint->GetPosition().y ) );
781 fprintf(
m_file,
"LAYER %s\n",
782 footprint->GetFlag() ?
"BOTTOM" :
"TOP" );
783 fprintf(
m_file,
"ROTATION %g\n",
785 fprintf(
m_file,
"SHAPE \"%s\" %s %s\n",
790 for(
PCB_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
795 fprintf(
m_file,
"TEXT %g %g %g %g %s %s \"%s\"",
799 textItem->GetTextAngle().AsDegrees(),
804 BOX2I textBox = textItem->GetTextBox();
806 fprintf(
m_file,
" 0 0 %g %g\n",
812 fprintf(
m_file,
"SHEET \"RefDes: %s, Value: %s\"\n",
813 TO_UTF8( footprint->GetReference() ),
814 TO_UTF8( footprint->GetValue() ) );
817 fputs(
"$ENDCOMPONENTS\n\n",
m_file );
830 fputs(
"$SIGNALS\n",
m_file );
840 msg.Printf( wxT(
"NoConnection%d" ), NbNoConn++ );
853 for(
PAD*
pad : footprint->Pads() )
858 msg.Printf( wxT(
"NODE \"%s\" \"%s\"" ),
869 fputs(
"$ENDSIGNALS\n\n",
m_file );
877 fputs(
"$HEADER\n",
m_file );
878 fputs(
"GENCAD 1.4\n",
m_file );
889 msg = wxT(
"REVISION \"" ) + rev + wxT(
" " ) + date + wxT(
"\"\n" );
892 fputs(
"UNITS INCH\n",
m_file );
895 msg.Printf( wxT(
"ORIGIN %g %g\n" ),
900 fputs(
"INTERTRACK 0\n",
m_file );
901 fputs(
"$ENDHEADER\n\n",
m_file );
920 int old_netcode, old_width, old_layer;
926 std::sort( tracks.begin(), tracks.end(),
929 if( a->GetNetCode() == b->GetNetCode() )
931 if( a->GetWidth() == b->GetWidth() )
932 return ( a->GetLayer() < b->GetLayer() );
934 return ( a->GetWidth() < b->GetWidth() );
940 fputs(
"$ROUTES\n", m_file );
942 old_netcode = -1; old_width = -1; old_layer = -1;
946 if( old_netcode != track->GetNetCode() )
948 old_netcode = track->GetNetCode();
952 if( net && (net->
GetNetname() != wxEmptyString) )
955 netname = wxT(
"_noname_" );
960 if( old_width != track->GetWidth() )
962 old_width = track->GetWidth();
963 fprintf( m_file,
"TRACK TRACK%d\n", track->GetWidth() );
968 if( old_layer != track->GetLayer() )
970 old_layer = track->GetLayer();
971 fprintf( m_file,
"LAYER %s\n",
975 fprintf( m_file,
"LINE %g %g %g %g\n",
976 MapXTo( track->GetStart().x ), MapYTo( track->GetStart().y ),
977 MapXTo( track->GetEnd().x ), MapYTo( track->GetEnd().y ) );
986 fprintf( m_file,
"VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
989 MapXTo(
via->GetStart().x ), MapYTo(
via->GetStart().y ),
994 fputs(
"$ENDROUTES\n\n", m_file );
1004 std::set<wxString> emitted;
1006 fputs(
"$DEVICES\n",
m_file );
1017 const wxString& shapeName =
shapeNames[componentShape.second];
1019 std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1024 const FOOTPRINT* footprint = componentShape.first;
1027 txt.Printf(
"\nDEVICE \"DEV_%s\"\n",
escapeString( shapeName ) );
1036 for( wxString& item : data )
1039 fputs(
"$ENDDEVICES\n\n",
m_file );
1048 fputs(
"$BOARD\n",
m_file );
1057 fprintf(
m_file,
"LINE %g %g %g %g\n",
1062 fputs(
"$ENDBOARD\n\n",
m_file );
1079 std::set<int> trackinfo;
1082 trackinfo.insert( track->GetWidth() );
1085 fputs(
"$TRACKS\n",
m_file );
1087 for(
int size : trackinfo )
1090 fputs(
"$ENDTRACKS\n\n",
m_file );
1105 fprintf(
m_file,
"INSERT TH\n" );
1107 fprintf(
m_file,
"INSERT SMD\n" );
1116 && ( item->GetLayer() ==
F_SilkS || item->GetLayer() ==
B_SilkS ) )
1129 case SHAPE_T::SEGMENT:
1130 fprintf(
m_file,
"LINE %g %g %g %g\n",
1137 case SHAPE_T::RECTANGLE:
1138 fprintf(
m_file,
"LINE %g %g %g %g\n",
1143 fprintf(
m_file,
"LINE %g %g %g %g\n",
1148 fprintf(
m_file,
"LINE %g %g %g %g\n",
1153 fprintf(
m_file,
"LINE %g %g %g %g\n",
1160 case SHAPE_T::CIRCLE:
1164 fprintf(
m_file,
"CIRCLE %g %g %g\n",
1173 std::swap( start, end );
1175 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
1189 wxFAIL_MSG( wxString::Format( wxT(
"Shape type %d invalid." ), item->Type() ) );
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
wxString GetBuildVersion()
Get the full KiCad version string.
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
TITLE_BLOCK & GetTitleBlock()
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
int GetCopperLayerCount() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
const wxString & GetFileName() const
PROJECT * GetProject() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
unsigned GetNetCount() const
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
EDA_ANGLE GetArcAngle() const
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void CreateComponentsSection()
void CreateBoardSection()
const wxString getShapeName(FOOTPRINT *aFootprint)
void CreateTracksInfoData()
void CreateShapesSection()
void CreateArtworksSection()
bool CreateHeaderInfoData()
Creates the header section.
void CreateSignalsSection()
void CreatePadsShapesSection()
void CreateRoutesSection()
void CreateDevicesSection()
bool m_useIndividualShapes
bool WriteFile(const wxString &aFullFileName)
Export a genCAD file.
void FootprintWriteShape(FOOTPRINT *aFootprint, const wxString &aShapeName)
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
LSET is a set of PCB_LAYER_IDs.
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
std::string FmtBin() const
Return a binary string showing contents of this LSEQ.
Handle the data for a net.
const wxString & GetNetname() const
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
static int Compare(const PAD *aPadRef, const PAD *aPadCmp)
Compare two pads and return 0 if they are equal.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
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.
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.
Represent a set of closed polygons.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
const wxString & GetRevision() const
const wxString & GetDate() const
double Distance(const VECTOR2< extended_type > &aVector) const
Compute the distance between two vectors.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
static constexpr EDA_ANGLE ANGLE_0
static std::map< int, wxString > shapeNames
static bool ViaSort(const PCB_VIA *aPadref, const PCB_VIA *aPadcmp)
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
static const double SCALE_FACTOR
static size_t hashFootprint(const FOOTPRINT *aFootprint)
Compute hashes for footprints without taking into account their position, rotation or layer.
static std::string fmt_mask(LSET aSet)
static std::map< FOOTPRINT *, int > componentShapes
static std::string GenCADLayerNameFlipped(int aCuCount, PCB_LAYER_ID aId)
static wxString escapeString(const wxString &aString)
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
@ HASH_POS
use coordinates relative to the parent object
@ REL_COORD
use coordinates relative to the shape position
bool IsCopperLayer(int aLayerId)
Tests whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define UNIMPLEMENTED_FOR(type)
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
void vset(double *v, double x, double y, double z)
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I