52#include <wx/filedlg.h>
74 else if( aId ==
B_Cu )
77 return StrPrintf(
"INNER%d", aCuCount - aId - 1 );
90 case B_Adhes: txt =
"B.Adhes";
break;
91 case F_Adhes: txt =
"F.Adhes";
break;
92 case B_Paste: txt =
"SOLDERPASTE_BOTTOM";
break;
93 case F_Paste: txt =
"SOLDERPASTE_TOP";
break;
94 case B_SilkS: txt =
"SILKSCREEN_BOTTOM";
break;
95 case F_SilkS: txt =
"SILKSCREEN_TOP";
break;
96 case B_Mask: txt =
"SOLDERMASK_BOTTOM";
break;
97 case F_Mask: txt =
"SOLDERMASK_TOP";
break;
100 case Dwgs_User: txt =
"Dwgs.User";
break;
101 case Cmts_User: txt =
"Cmts.User";
break;
102 case Eco1_User: txt =
"Eco1.User";
break;
103 case Eco2_User: txt =
"Eco2.User";
break;
104 case Edge_Cuts: txt =
"Edge.Cuts";
break;
105 case Margin: txt =
"Margin";
break;
108 case F_CrtYd: txt =
"F_CrtYd";
break;
109 case B_CrtYd: txt =
"B_CrtYd";
break;
110 case F_Fab: txt =
"F_Fab";
break;
111 case B_Fab: txt =
"B_Fab";
break;
114 wxASSERT_MSG( 0, wxT(
"aId UNEXPECTED" ) );
115 txt =
"BAD-INDEX!";
break;
162 if( 1<= aId && aId <= 14 )
171 wxString
copy( aString );
172 copy.Replace( wxT(
"\"" ), wxT(
"\\\"" ) );
199 static const wxString invalid(
"invalid" );
207 auto itName =
shapeNames.find( itShape->second );
208 wxCHECK( itName !=
shapeNames.end(), invalid );
210 return itName->second;
242 brdFile.SetExt( wxT(
"cad" ) );
243 path = brdFile.GetFullPath();
248 if( optionsDialog.ShowModal() == wxID_CANCEL )
253 FILE* file = wxFopen(
path, wxT(
"wt" ) );
292 footprint->SetFlag( 0 );
294 if( footprint->GetLayer() ==
B_Cu )
296 footprint->Flip( footprint->GetPosition(),
false );
297 footprint->SetFlag( 1 );
328 if( footprint->GetFlag() )
330 footprint->Flip( footprint->GetPosition(),
false );
331 footprint->SetFlag( 0 );
360 fputs(
"$ARTWORKS\n", aFile );
361 fputs(
"$ENDARTWORKS\n\n", aFile );
369 std::vector<PAD*> padstacks;
370 std::vector<PCB_VIA*> vias;
371 std::vector<PCB_VIA*> viastacks;
373 padstacks.resize( 1 );
379 fputs(
"$PADS\n", aFile );
383 std::vector<PAD*> pads = aPcb->
GetPads();
384 std::sort( pads.begin(), pads.end(), [](
const PAD* a,
const PAD* b )
386 return PAD::Compare( a, b ) < 0;
393 if(
PCB_VIA*
via = dyn_cast<PCB_VIA*>( track ) )
394 vias.push_back(
via );
397 std::sort( vias.begin(), vias.end(),
ViaSort );
398 vias.erase( std::unique( vias.begin(), vias.end(), [](
const PCB_VIA* a,
const PCB_VIA* b )
400 return ViaSort( a, b ) == false;
407 viastacks.push_back(
via );
408 fprintf( aFile,
"PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
409 via->GetWidth(),
via->GetDrillValue(),
410 fmt_mask(
via->GetLayerSet() & master_layermask ).c_str(),
416 PAD* old_pad =
nullptr;
417 int pad_name_number = 0;
419 for(
unsigned i = 0; i<pads.size(); ++i )
424 pad->SetSubRatsnest( pad_name_number );
434 pad->SetSubRatsnest( pad_name_number );
436 fprintf( aFile,
"PAD P%d",
pad->GetSubRatsnest() );
438 padstacks.push_back(
pad );
439 int dx =
pad->GetSize().x / 2;
440 int dy =
pad->GetSize().y / 2;
442 switch(
pad->GetShape() )
449 fprintf( aFile,
" ROUND %g\n",
453 fprintf( aFile,
"CIRCLE %g %g %g\n",
460 fprintf( aFile,
" RECTANGULAR %g\n",
464 fprintf( aFile,
"RECTANGLE %g %g %g %g\n",
474 int radius = std::min( size.
x, size.
y ) / 2;
478 radius =
pad->GetRoundRectCornerRadius();
481 int lineX = size.
x / 2 - radius;
482 int lineY = size.
y / 2 - radius;
484 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
487 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
496 fprintf( aFile,
"LINE %g %g %g %g\n",
504 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
514 fprintf( aFile,
"LINE %g %g %g %g\n",
522 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
531 fprintf( aFile,
"LINE %g %g %g %g\n"
539 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
549 fprintf( aFile,
"LINE %g %g %g %g\n",
561 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
563 int ddx =
pad->GetDelta().x / 2;
564 int ddy =
pad->GetDelta().y / 2;
567 poly[0] =
VECTOR2I( -dx + ddy, dy + ddx );
568 poly[1] =
VECTOR2I( dx - ddy, dy - ddx );
569 poly[2] =
VECTOR2I( dx + ddy, -dy + ddx );
570 poly[3] =
VECTOR2I( -dx - ddy, -dy - ddx );
572 for(
int cur = 0; cur < 4; ++cur )
574 int next = ( cur + 1 ) % 4;
575 fprintf( aFile,
"LINE %g %g %g %g\n",
587 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
594 pad->GetOrientation(),
595 pad->GetRoundRectCornerRadius(),
596 pad->GetChamferRectRatio(),
597 pad->GetChamferPositions(), 0, maxError,
605 for(
int ii = 0; ii < pointCount; ii++ )
607 int next = ( ii + 1 ) % pointCount;
608 fprintf( aFile,
"LINE %g %g %g %g\n",
621 fprintf( aFile,
" POLYGON %g\n",
pad->GetDrillSize().x /
SCALE_FACTOR );
624 pad->MergePrimitivesAsPolygon( &outline );
631 for(
int ii = 0; ii < pointCount; ii++ )
633 int next = ( ii + 1 ) % pointCount;
634 fprintf( aFile,
"LINE %g %g %g %g\n",
647 fputs(
"\n$ENDPADS\n\n", aFile );
650 fputs(
"$PADSTACKS\n", aFile );
653 for(
unsigned i = 0; i < viastacks.size(); i++ )
657 LSET mask =
via->GetLayerSet() & master_layermask;
659 fprintf( aFile,
"PADSTACK VIA%d.%d.%s %g\n",
660 via->GetWidth(),
via->GetDrillValue(),
668 fprintf( aFile,
"PAD V%d.%d.%s %s 0 0\n",
669 via->GetWidth(),
via->GetDrillValue(),
680 for(
unsigned i = 1; i < padstacks.size(); i++ )
685 fprintf( aFile,
"PADSTACK PAD%u %g\n", i,
pad->GetDrillSize().x /
SCALE_FACTOR );
687 LSET pad_set =
pad->GetLayerSet() & master_layermask;
694 fprintf( aFile,
"PAD P%u %s 0 0\n", i,
GenCADLayerName( cu_count, layer ).c_str() );
700 fprintf( aFile,
"PADSTACK PAD%uF %g\n", i,
pad->GetDrillSize().x /
SCALE_FACTOR );
703 for(
LSEQ seq = pad_set.
Seq(); seq; ++seq )
707 fprintf( aFile,
"PAD P%u %s 0 0\n", i,
713 fputs(
"$ENDPADSTACKS\n\n", aFile );
720 size_t ret = 0x11223344;
727 for(
PAD* i : aFootprint->
Pads() )
742 const char* mirror =
"0";
743 std::map<wxString, size_t> shapes;
745 fputs(
"$SHAPES\n", aFile );
755 wxString shapeName = footprint->GetFPID().Format();
757 auto shapeIt = shapes.find( shapeName );
760 if( shapeIt != shapes.end() )
762 if( modHash != shapeIt->second )
766 wxString newShapeName;
773 shapeIt = shapes.find( newShapeName );
776 while( shapeIt != shapes.end() && shapeIt->second != modHash );
778 shapeName = newShapeName;
781 if( shapeIt != shapes.end() && modHash == shapeIt->second )
792 shapes[shapeName] = modHash;
801 std::set<wxString> pins;
803 for(
PAD*
pad : footprint->Pads() )
809 pinname =
pad->GetNumber();
811 if( pinname.IsEmpty() )
812 pinname = wxT(
"none" );
817 wxString origPinname( pinname );
819 auto it = pins.find( pinname );
821 while( it != pins.end() )
825 it = pins.find( pinname );
828 pins.insert( pinname );
831 EDA_ANGLE orient =
pad->GetOrientation() - footprint->GetOrientation();
836 "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
837 "PIN \"%s\" PAD%d %g %g %s %g %s\n",
845 fputs(
"$ENDSHAPES\n\n", aFile );
856 fputs(
"$COMPONENTS\n", aFile );
864 EDA_ANGLE fp_orient = footprint->GetOrientation();
866 if( footprint->GetFlag() )
878 fprintf( aFile,
"\nCOMPONENT \"%s\"\n",
880 fprintf( aFile,
"DEVICE \"DEV_%s\"\n",
882 fprintf( aFile,
"PLACE %g %g\n",
883 MapXTo( footprint->GetPosition().x ),
884 MapYTo( footprint->GetPosition().y ) );
885 fprintf( aFile,
"LAYER %s\n",
886 footprint->GetFlag() ?
"BOTTOM" :
"TOP" );
887 fprintf( aFile,
"ROTATION %g\n",
889 fprintf( aFile,
"SHAPE \"%s\" %s %s\n",
894 for(
FP_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
899 fprintf( aFile,
"TEXT %g %g %g %g %s %s \"%s\"",
903 textItem->GetTextAngle().AsDegrees(),
909 fprintf( aFile,
" 0 0 %g %g\n",
910 ( textItem->GetTextWidth() * textItem->GetLength() ) /
SCALE_FACTOR,
915 fprintf( aFile,
"SHEET \"RefDes: %s, Value: %s\"\n",
916 TO_UTF8( footprint->GetReference() ),
917 TO_UTF8( footprint->GetValue() ) );
920 fputs(
"$ENDCOMPONENTS\n\n", aFile );
932 fputs(
"$SIGNALS\n", aFile );
934 for(
unsigned ii = 0; ii < aPcb->
GetNetCount(); ii++ )
942 msg.Printf( wxT(
"NoConnection%d" ), NbNoConn++ );
950 fputs(
TO_UTF8( msg ), aFile );
951 fputs(
"\n", aFile );
955 for(
PAD*
pad : footprint->Pads() )
960 msg.Printf( wxT(
"NODE \"%s\" \"%s\"" ),
964 fputs(
TO_UTF8( msg ), aFile );
965 fputs(
"\n", aFile );
971 fputs(
"$ENDSIGNALS\n\n", aFile );
981 fputs(
"$HEADER\n", aFile );
982 fputs(
"GENCAD 1.4\n", aFile );
985 msg.Printf( wxT(
"USER \"%s %s\"\n" ),
986 Pgm().App().GetAppName(),
988 fputs(
TO_UTF8( msg ), aFile );
990 msg = wxT(
"DRAWING \"" ) + board->
GetFileName() + wxT(
"\"\n" );
991 fputs(
TO_UTF8( msg ), aFile );
995 msg = wxT(
"REVISION \"" ) + rev + wxT(
" " ) + date + wxT(
"\"\n" );
997 fputs(
TO_UTF8( msg ), aFile );
998 fputs(
"UNITS INCH\n", aFile );
1001 msg.Printf( wxT(
"ORIGIN %g %g\n" ),
1004 fputs(
TO_UTF8( msg ), aFile );
1006 fputs(
"INTERTRACK 0\n", aFile );
1007 fputs(
"$ENDHEADER\n\n", aFile );
1025 int old_netcode, old_width, old_layer;
1030 TRACKS tracks( aPcb->
Tracks() );
1031 std::sort( tracks.begin(), tracks.end(),
1034 if( a->GetNetCode() == b->GetNetCode() )
1036 if( a->GetWidth() == b->GetWidth() )
1037 return ( a->GetLayer() < b->GetLayer() );
1039 return ( a->GetWidth() < b->GetWidth() );
1045 fputs(
"$ROUTES\n", aFile );
1047 old_netcode = -1; old_width = -1; old_layer = -1;
1051 if( old_netcode != track->GetNetCode() )
1053 old_netcode = track->GetNetCode();
1057 if( net && (net->
GetNetname() != wxEmptyString) )
1060 netname = wxT(
"_noname_" );
1065 if( old_width != track->GetWidth() )
1067 old_width = track->GetWidth();
1068 fprintf( aFile,
"TRACK TRACK%d\n", track->GetWidth() );
1073 if( old_layer != track->GetLayer() )
1075 old_layer = track->GetLayer();
1076 fprintf( aFile,
"LAYER %s\n",
1080 fprintf( aFile,
"LINE %g %g %g %g\n",
1081 MapXTo( track->GetStart().x ),
MapYTo( track->GetStart().y ),
1082 MapXTo( track->GetEnd().x ),
MapYTo( track->GetEnd().y ) );
1089 LSET vset =
via->GetLayerSet() & master_layermask;
1091 fprintf( aFile,
"VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1092 via->GetWidth(),
via->GetDrillValue(),
1099 fputs(
"$ENDROUTES\n\n", aFile );
1109 std::set<wxString> emitted;
1110 fputs(
"$DEVICES\n", aFile );
1114 const wxString& shapeName =
shapeNames[componentShape.second];
1116 std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1121 const FOOTPRINT* footprint = componentShape.first;
1125 fprintf( aFile,
"PART \"%s\"\n",
1128 fprintf( aFile,
"PACKAGE \"%s\"\n",
1132 fputs(
"$ENDDEVICES\n\n", aFile );
1141 fputs(
"$BOARD\n", aFile );
1153 fprintf( aFile,
"LINE %g %g %g %g\n",
1160 fputs(
"$ENDBOARD\n\n", aFile );
1178 std::set<int> trackinfo;
1181 trackinfo.insert( track->GetWidth() );
1184 fputs(
"$TRACKS\n", aFile );
1186 for(
int size : trackinfo )
1187 fprintf( aFile,
"TRACK TRACK%d %g\n", size, size /
SCALE_FACTOR );
1189 fputs(
"$ENDTRACKS\n\n", aFile );
1206 fprintf( aFile,
"INSERT TH\n" );
1208 fprintf( aFile,
"INSERT SMD\n" );
1216 switch( PtStruct->Type() )
1232 fprintf( aFile,
"LINE %g %g %g %g\n",
1241 fprintf( aFile,
"LINE %g %g %g %g\n",
1246 fprintf( aFile,
"LINE %g %g %g %g\n",
1251 fprintf( aFile,
"LINE %g %g %g %g\n",
1256 fprintf( aFile,
"LINE %g %g %g %g\n",
1268 fprintf( aFile,
"CIRCLE %g %g %g\n",
1281 std::swap( start, end );
1283 fprintf( aFile,
"ARC %g %g %g %g %g %g\n",
1299 PtStruct->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...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
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
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.
const VECTOR2I & GetEnd0() const
VECTOR2I GetCenter0() const
const VECTOR2I & GetStart0() const
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.
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
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 vertices in a given outline/hole.
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
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)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
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.
void vset(double *v, double x, double y, double z)
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_FP_SHAPE_T
class FP_SHAPE, a footprint edge
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
@ 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".