73 else if( aId ==
B_Cu )
76 return StrPrintf(
"INNER%d", aCuCount - aId - 1 );
89 case B_Adhes: txt =
"B.Adhes";
break;
90 case F_Adhes: txt =
"F.Adhes";
break;
91 case B_Paste: txt =
"SOLDERPASTE_BOTTOM";
break;
92 case F_Paste: txt =
"SOLDERPASTE_TOP";
break;
93 case B_SilkS: txt =
"SILKSCREEN_BOTTOM";
break;
94 case F_SilkS: txt =
"SILKSCREEN_TOP";
break;
95 case B_Mask: txt =
"SOLDERMASK_BOTTOM";
break;
96 case F_Mask: txt =
"SOLDERMASK_TOP";
break;
100 case Cmts_User: txt =
"Cmts.User";
break;
101 case Eco1_User: txt =
"Eco1.User";
break;
102 case Eco2_User: txt =
"Eco2.User";
break;
103 case Edge_Cuts: txt =
"Edge.Cuts";
break;
104 case Margin: txt =
"Margin";
break;
107 case F_CrtYd: txt =
"F_CrtYd";
break;
108 case B_CrtYd: txt =
"B_CrtYd";
break;
109 case F_Fab: txt =
"F_Fab";
break;
110 case B_Fab: txt =
"B_Fab";
break;
113 wxASSERT_MSG( 0, wxT(
"aId UNEXPECTED" ) );
114 txt =
"BAD-INDEX!";
break;
161 if( 1<= aId && aId <= 14 )
170 wxString
copy( aString );
171 copy.Replace( wxT(
"\"" ), wxT(
"\\\"" ) );
198 static const wxString invalid(
"invalid" );
206 auto itName =
shapeNames.find( itShape->second );
207 wxCHECK( itName !=
shapeNames.end(), invalid );
209 return itName->second;
241 brdFile.SetExt( wxT(
"cad" ) );
242 path = brdFile.GetFullPath();
247 if( optionsDialog.ShowModal() == wxID_CANCEL )
252 FILE* file = wxFopen(
path, wxT(
"wt" ) );
256 DisplayError(
this, wxString::Format(
_(
"Failed to create file '%s'." ),
291 footprint->SetFlag( 0 );
293 if( footprint->GetLayer() ==
B_Cu )
295 footprint->Flip( footprint->GetPosition(),
false );
296 footprint->SetFlag( 1 );
327 if( footprint->GetFlag() )
329 footprint->Flip( footprint->GetPosition(),
false );
330 footprint->SetFlag( 0 );
359 fputs(
"$ARTWORKS\n", aFile );
360 fputs(
"$ENDARTWORKS\n\n", aFile );
368 std::vector<PAD*> padstacks;
369 std::vector<PCB_VIA*> vias;
370 std::vector<PCB_VIA*> viastacks;
372 padstacks.resize( 1 );
378 fputs(
"$PADS\n", aFile );
382 std::vector<PAD*> pads = aPcb->
GetPads();
383 std::sort( pads.begin(), pads.end(), [](
const PAD* a,
const PAD* b )
385 return PAD::Compare( a, b ) < 0;
392 if(
PCB_VIA*
via = dyn_cast<PCB_VIA*>( track ) )
393 vias.push_back(
via );
396 std::sort( vias.begin(), vias.end(),
ViaSort );
397 vias.erase( std::unique( vias.begin(), vias.end(), [](
const PCB_VIA* a,
const PCB_VIA* b )
399 return ViaSort( a, b ) == false;
406 viastacks.push_back(
via );
407 fprintf( aFile,
"PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
408 via->GetWidth(),
via->GetDrillValue(),
409 fmt_mask(
via->GetLayerSet() & master_layermask ).c_str(),
415 PAD* old_pad =
nullptr;
416 int pad_name_number = 0;
418 for(
unsigned i = 0; i<pads.size(); ++i )
423 pad->SetSubRatsnest( pad_name_number );
433 pad->SetSubRatsnest( pad_name_number );
435 fprintf( aFile,
"PAD P%d",
pad->GetSubRatsnest() );
437 padstacks.push_back(
pad );
438 int dx =
pad->GetSize().x / 2;
439 int dy =
pad->GetSize().y / 2;
441 switch(
pad->GetShape() )
448 fprintf( aFile,
" ROUND %g\n",
452 fprintf( aFile,
"CIRCLE %g %g %g\n",
459 fprintf( aFile,
" RECTANGULAR %g\n",
463 fprintf( aFile,
"RECTANGLE %g %g %g %g\n",
473 int radius = std::min( size.
x, size.
y ) / 2;
477 radius =
pad->GetRoundRectCornerRadius();
480 int lineX = size.
x / 2 - radius;
481 int lineY = size.
y / 2 - radius;
483 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
486 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
495 fprintf( aFile,
"LINE %g %g %g %g\n",
503 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
513 fprintf( aFile,
"LINE %g %g %g %g\n",
521 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
530 fprintf( aFile,
"LINE %g %g %g %g\n"
538 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
548 fprintf( aFile,
"LINE %g %g %g %g\n",
560 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
562 int ddx =
pad->GetDelta().x / 2;
563 int ddy =
pad->GetDelta().y / 2;
566 poly[0] =
VECTOR2I( -dx + ddy, dy + ddx );
567 poly[1] =
VECTOR2I( dx - ddy, dy - ddx );
568 poly[2] =
VECTOR2I( dx + ddy, -dy + ddx );
569 poly[3] =
VECTOR2I( -dx - ddy, -dy - ddx );
571 for(
int cur = 0; cur < 4; ++cur )
573 int next = ( cur + 1 ) % 4;
574 fprintf( aFile,
"LINE %g %g %g %g\n",
586 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
593 pad->GetOrientation(),
594 pad->GetRoundRectCornerRadius(),
595 pad->GetChamferRectRatio(),
596 pad->GetChamferPositions(), 0, maxError,
604 for(
int ii = 0; ii < pointCount; ii++ )
606 int next = ( ii + 1 ) % pointCount;
607 fprintf( aFile,
"LINE %g %g %g %g\n",
620 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
623 pad->MergePrimitivesAsPolygon( &outline );
630 for(
int ii = 0; ii < pointCount; ii++ )
632 int next = ( ii + 1 ) % pointCount;
633 fprintf( aFile,
"LINE %g %g %g %g\n",
646 fputs(
"\n$ENDPADS\n\n", aFile );
649 fputs(
"$PADSTACKS\n", aFile );
652 for(
unsigned i = 0; i < viastacks.size(); i++ )
656 LSET mask =
via->GetLayerSet() & master_layermask;
658 fprintf( aFile,
"PADSTACK VIA%d.%d.%s %g\n",
659 via->GetWidth(),
via->GetDrillValue(),
667 fprintf( aFile,
"PAD V%d.%d.%s %s 0 0\n",
668 via->GetWidth(),
via->GetDrillValue(),
679 for(
unsigned i = 1; i < padstacks.size(); i++ )
684 fprintf( aFile,
"PADSTACK PAD%u %g\n", i,
pad->GetDrillSize().x /
SCALE_FACTOR );
686 LSET pad_set =
pad->GetLayerSet() & master_layermask;
693 fprintf( aFile,
"PAD P%u %s 0 0\n", i,
GenCADLayerName( cu_count, layer ).c_str() );
699 fprintf( aFile,
"PADSTACK PAD%uF %g\n", i,
pad->GetDrillSize().x /
SCALE_FACTOR );
702 for(
LSEQ seq = pad_set.
Seq(); seq; ++seq )
706 fprintf( aFile,
"PAD P%u %s 0 0\n", i,
712 fputs(
"$ENDPADSTACKS\n\n", aFile );
719 size_t ret = 0x11223344;
729 for(
PAD* i : aFootprint->
Pads() )
744 const char* mirror =
"0";
745 std::map<wxString, size_t> shapes;
747 fputs(
"$SHAPES\n", aFile );
757 wxString shapeName = footprint->GetFPID().Format();
759 auto shapeIt = shapes.find( shapeName );
762 if( shapeIt != shapes.end() )
764 if( modHash != shapeIt->second )
768 wxString newShapeName;
774 newShapeName = wxString::Format( wxT(
"%s_%d" ), shapeName, suffix );
775 shapeIt = shapes.find( newShapeName );
778 while( shapeIt != shapes.end() && shapeIt->second != modHash );
780 shapeName = newShapeName;
783 if( shapeIt != shapes.end() && modHash == shapeIt->second )
794 shapes[shapeName] = modHash;
803 std::set<wxString> pins;
805 for(
PAD*
pad : footprint->Pads() )
811 pinname =
pad->GetNumber();
813 if( pinname.IsEmpty() )
814 pinname = wxT(
"none" );
819 wxString origPinname( pinname );
821 auto it = pins.find( pinname );
823 while( it != pins.end() )
825 pinname = wxString::Format( wxT(
"%s_%d" ), origPinname, suffix );
827 it = pins.find( pinname );
830 pins.insert( pinname );
833 EDA_ANGLE orient =
pad->GetOrientation() - footprint->GetOrientation();
840 "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
841 "PIN \"%s\" PAD%d %g %g %s %g %s\n",
849 fputs(
"$ENDSHAPES\n\n", aFile );
860 fputs(
"$COMPONENTS\n", aFile );
868 EDA_ANGLE fp_orient = footprint->GetOrientation();
870 if( footprint->GetFlag() )
882 fprintf( aFile,
"\nCOMPONENT \"%s\"\n",
884 fprintf( aFile,
"DEVICE \"DEV_%s\"\n",
886 fprintf( aFile,
"PLACE %g %g\n",
887 MapXTo( footprint->GetPosition().x ),
888 MapYTo( footprint->GetPosition().y ) );
889 fprintf( aFile,
"LAYER %s\n",
890 footprint->GetFlag() ?
"BOTTOM" :
"TOP" );
891 fprintf( aFile,
"ROTATION %g\n",
893 fprintf( aFile,
"SHAPE \"%s\" %s %s\n",
898 for(
PCB_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
903 fprintf( aFile,
"TEXT %g %g %g %g %s %s \"%s\"",
907 textItem->GetTextAngle().AsDegrees(),
912 BOX2I textBox = textItem->GetTextBox();
914 fprintf( aFile,
" 0 0 %g %g\n",
920 fprintf( aFile,
"SHEET \"RefDes: %s, Value: %s\"\n",
921 TO_UTF8( footprint->GetReference() ),
922 TO_UTF8( footprint->GetValue() ) );
925 fputs(
"$ENDCOMPONENTS\n\n", aFile );
937 fputs(
"$SIGNALS\n", aFile );
939 for(
unsigned ii = 0; ii < aPcb->
GetNetCount(); ii++ )
947 msg.Printf( wxT(
"NoConnection%d" ), NbNoConn++ );
955 fputs(
TO_UTF8( msg ), aFile );
956 fputs(
"\n", aFile );
960 for(
PAD*
pad : footprint->Pads() )
965 msg.Printf( wxT(
"NODE \"%s\" \"%s\"" ),
969 fputs(
TO_UTF8( msg ), aFile );
970 fputs(
"\n", aFile );
976 fputs(
"$ENDSIGNALS\n\n", aFile );
986 fputs(
"$HEADER\n", aFile );
987 fputs(
"GENCAD 1.4\n", aFile );
990 msg.Printf( wxT(
"USER \"%s %s\"\n" ),
991 Pgm().App().GetAppName(),
993 fputs(
TO_UTF8( msg ), aFile );
995 msg = wxT(
"DRAWING \"" ) + board->
GetFileName() + wxT(
"\"\n" );
996 fputs(
TO_UTF8( msg ), aFile );
1000 msg = wxT(
"REVISION \"" ) + rev + wxT(
" " ) + date + wxT(
"\"\n" );
1002 fputs(
TO_UTF8( msg ), aFile );
1003 fputs(
"UNITS INCH\n", aFile );
1006 msg.Printf( wxT(
"ORIGIN %g %g\n" ),
1009 fputs(
TO_UTF8( msg ), aFile );
1011 fputs(
"INTERTRACK 0\n", aFile );
1012 fputs(
"$ENDHEADER\n\n", aFile );
1030 int old_netcode, old_width, old_layer;
1035 TRACKS tracks( aPcb->
Tracks() );
1036 std::sort( tracks.begin(), tracks.end(),
1039 if( a->GetNetCode() == b->GetNetCode() )
1041 if( a->GetWidth() == b->GetWidth() )
1042 return ( a->GetLayer() < b->GetLayer() );
1044 return ( a->GetWidth() < b->GetWidth() );
1050 fputs(
"$ROUTES\n", aFile );
1052 old_netcode = -1; old_width = -1; old_layer = -1;
1056 if( old_netcode != track->GetNetCode() )
1058 old_netcode = track->GetNetCode();
1062 if( net && (net->
GetNetname() != wxEmptyString) )
1065 netname = wxT(
"_noname_" );
1070 if( old_width != track->GetWidth() )
1072 old_width = track->GetWidth();
1073 fprintf( aFile,
"TRACK TRACK%d\n", track->GetWidth() );
1078 if( old_layer != track->GetLayer() )
1080 old_layer = track->GetLayer();
1081 fprintf( aFile,
"LAYER %s\n",
1085 fprintf( aFile,
"LINE %g %g %g %g\n",
1086 MapXTo( track->GetStart().x ),
MapYTo( track->GetStart().y ),
1087 MapXTo( track->GetEnd().x ),
MapYTo( track->GetEnd().y ) );
1094 LSET vset =
via->GetLayerSet() & master_layermask;
1096 fprintf( aFile,
"VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1097 via->GetWidth(),
via->GetDrillValue(),
1104 fputs(
"$ENDROUTES\n\n", aFile );
1114 std::set<wxString> emitted;
1115 fputs(
"$DEVICES\n", aFile );
1119 const wxString& shapeName =
shapeNames[componentShape.second];
1121 std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1126 const FOOTPRINT* footprint = componentShape.first;
1130 fprintf( aFile,
"PART \"%s\"\n",
1133 fprintf( aFile,
"PACKAGE \"%s\"\n",
1137 fputs(
"$ENDDEVICES\n\n", aFile );
1146 fputs(
"$BOARD\n", aFile );
1158 fprintf( aFile,
"LINE %g %g %g %g\n",
1165 fputs(
"$ENDBOARD\n\n", aFile );
1183 std::set<int> trackinfo;
1186 trackinfo.insert( track->GetWidth() );
1189 fputs(
"$TRACKS\n", aFile );
1191 for(
int size : trackinfo )
1192 fprintf( aFile,
"TRACK TRACK%d %g\n", size, size /
SCALE_FACTOR );
1194 fputs(
"$ENDTRACKS\n\n", aFile );
1209 fprintf( aFile,
"INSERT TH\n" );
1211 fprintf( aFile,
"INSERT SMD\n" );
1220 && ( item->GetLayer() ==
F_SilkS || item->GetLayer() ==
B_SilkS ) )
1234 fprintf( aFile,
"LINE %g %g %g %g\n",
1242 fprintf( aFile,
"LINE %g %g %g %g\n",
1247 fprintf( aFile,
"LINE %g %g %g %g\n",
1252 fprintf( aFile,
"LINE %g %g %g %g\n",
1257 fprintf( aFile,
"LINE %g %g %g %g\n",
1268 fprintf( aFile,
"CIRCLE %g %g %g\n",
1277 std::swap( start, end );
1279 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
1293 wxFAIL_MSG( wxString::Format( wxT(
"Shape type %d invalid." ), item->Type() ) );
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
constexpr EDA_IU_SCALE pcbIUScale
wxString GetBuildVersion()
Get the full KiCad version string.
LSET GetEnabledLayers() const
Return a bit-mask of all the layers that are enabled.
const VECTOR2I & GetAuxOrigin()
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.
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).
FOOTPRINTS & Footprints()
int GetCopperLayerCount() const
const wxString & GetFileName() const
PROJECT * GetProject() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
unsigned GetNetCount() const
coord_type GetHeight() const
coord_type GetWidth() const
bool GetOption(GENCAD_EXPORT_OPT aOption) const
Return all export settings.
wxString GetFileName() 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.
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 Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
std::string FmtBin() const
Return a binary string showing contents of this LSEQ.
Handle the data for a net.
const wxString & GetNetname() const
static int Compare(const PAD *aPadRef, const PAD *aPadCmp)
Compare two pads and return 0 if they are equal.
void Compile_Ratsnest(bool aDisplayStatus)
Create the entire board ratsnest.
The main frame for Pcbnew.
void SetLastPath(LAST_PATH_TYPE aType, const wxString &aLastPath)
Set the path of the last file successfully read.
wxString GetLastPath(LAST_PATH_TYPE aType)
Get the last path for a particular type.
void ExportToGenCAD(wxCommandEvent &event)
Create a file in GenCAD 1.4 format from the current board.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
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
const wxString & GetRevision() const
const wxString & GetDate() const
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
This file is part of the common library.
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
@ ARC
use RECTANGLE instead of RECT to avoid collision in a Windows header
static std::map< int, wxString > shapeNames
static const wxString getShapeName(FOOTPRINT *aFootprint)
static bool ViaSort(const PCB_VIA *aPadref, const PCB_VIA *aPadcmp)
static std::string GenCADLayerName(int aCuCount, PCB_LAYER_ID aId)
static void CreateTracksInfoData(FILE *aFile, BOARD *aPcb)
static const PCB_LAYER_ID gc_seq[]
static const double SCALE_FACTOR
static bool flipBottomPads
static size_t hashFootprint(const FOOTPRINT *aFootprint)
Compute hashes for footprints without taking into account their position, rotation or layer.
static void CreatePadsShapesSection(FILE *aFile, BOARD *aPcb)
static bool storeOriginCoords
static void CreateRoutesSection(FILE *aFile, BOARD *aPcb)
static std::string fmt_mask(LSET aSet)
static double MapXTo(int aX)
static bool CreateHeaderInfoData(FILE *aFile, PCB_EDIT_FRAME *frame)
static void FootprintWriteShape(FILE *File, FOOTPRINT *aFootprint, const wxString &aShapeName)
static std::map< FOOTPRINT *, int > componentShapes
static bool individualShapes
static void CreateBoardSection(FILE *aFile, BOARD *aPcb)
static void CreateShapesSection(FILE *aFile, BOARD *aPcb)
static void CreateDevicesSection(FILE *aFile, BOARD *aPcb)
static double MapYTo(int aY)
static std::string GenCADLayerNameFlipped(int aCuCount, PCB_LAYER_ID aId)
static void CreateComponentsSection(FILE *aFile, BOARD *aPcb)
static wxString escapeString(const wxString &aString)
static void CreateArtworksSection(FILE *aFile)
static void CreateSignalsSection(FILE *aFile, BOARD *aPcb)
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
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.
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
#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)
double GetLineLength(const VECTOR2I &aPointA, const VECTOR2I &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
@ 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)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".