42 else if( aId ==
B_Cu )
45 return StrPrintf(
"INNER%d", aCuCount - aId - 1 );
58 case B_Adhes: txt =
"B.Adhes";
break;
59 case F_Adhes: txt =
"F.Adhes";
break;
60 case B_Paste: txt =
"SOLDERPASTE_BOTTOM";
break;
61 case F_Paste: txt =
"SOLDERPASTE_TOP";
break;
62 case B_SilkS: txt =
"SILKSCREEN_BOTTOM";
break;
63 case F_SilkS: txt =
"SILKSCREEN_TOP";
break;
64 case B_Mask: txt =
"SOLDERMASK_BOTTOM";
break;
65 case F_Mask: txt =
"SOLDERMASK_TOP";
break;
73 case Margin: txt =
"Margin";
break;
76 case F_CrtYd: txt =
"F_CrtYd";
break;
77 case B_CrtYd: txt =
"B_CrtYd";
break;
78 case F_Fab: txt =
"F_Fab";
break;
79 case B_Fab: txt =
"B_Fab";
break;
82 wxASSERT_MSG( 0, wxT(
"aId UNEXPECTED" ) );
83 txt =
"BAD-INDEX!";
break;
130 if( 1<= aId && aId <= 14 )
139 wxString
copy( aString );
140 copy.Replace( wxT(
"\"" ), wxT(
"\\\"" ) );
158 static const wxString invalid(
"invalid" );
166 auto itName =
shapeNames.find( itShape->second );
167 wxCHECK( itName !=
shapeNames.end(), invalid );
169 return itName->second;
197 m_file = wxFopen( aFullFileName, wxT(
"wt" ) );
218 footprint->SetFlag( 0 );
220 if( footprint->GetLayer() ==
B_Cu )
222 footprint->Flip( footprint->GetPosition(),
false );
223 footprint->SetFlag( 1 );
254 if( footprint->GetFlag() )
256 footprint->Flip( footprint->GetPosition(),
false );
257 footprint->SetFlag( 0 );
287 fputs(
"$ARTWORKS\n",
m_file );
288 fputs(
"$ENDARTWORKS\n\n",
m_file );
297 std::vector<PAD*> padstacks;
298 std::vector<PCB_VIA*> vias;
299 std::vector<PCB_VIA*> viastacks;
301 padstacks.resize( 1 );
307 fputs(
"$PADS\n",
m_file );
312 std::sort( pads.begin(), pads.end(), [](
const PAD* a,
const PAD* b )
314 return PAD::Compare( a, b ) < 0;
321 if(
PCB_VIA*
via = dyn_cast<PCB_VIA*>( track ) )
322 vias.push_back(
via );
325 std::sort( vias.begin(), vias.end(),
ViaSort );
326 vias.erase( std::unique( vias.begin(), vias.end(), [](
const PCB_VIA* a,
const PCB_VIA* b )
328 return ViaSort( a, b ) == false;
335 viastacks.push_back(
via );
336 fprintf(
m_file,
"PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
337 via->GetWidth(),
via->GetDrillValue(),
338 fmt_mask(
via->GetLayerSet() & master_layermask ).c_str(),
344 PAD* old_pad =
nullptr;
345 int pad_name_number = 0;
347 for(
unsigned i = 0; i<pads.size(); ++i )
352 pad->SetSubRatsnest( pad_name_number );
362 pad->SetSubRatsnest( pad_name_number );
364 fprintf(
m_file,
"PAD P%d",
pad->GetSubRatsnest() );
366 padstacks.push_back(
pad );
367 int dx =
pad->GetSize().x / 2;
368 int dy =
pad->GetSize().y / 2;
370 switch(
pad->GetShape() )
376 case PAD_SHAPE::CIRCLE:
377 fprintf(
m_file,
" ROUND %g\n",
381 fprintf(
m_file,
"CIRCLE %g %g %g\n",
387 case PAD_SHAPE::RECTANGLE:
388 fprintf(
m_file,
" RECTANGULAR %g\n",
392 fprintf(
m_file,
"RECTANGLE %g %g %g %g\n",
398 case PAD_SHAPE::ROUNDRECT:
399 case PAD_SHAPE::OVAL:
402 int radius = std::min( size.
x, size.
y ) / 2;
404 if(
pad->GetShape() == PAD_SHAPE::ROUNDRECT )
406 radius =
pad->GetRoundRectCornerRadius();
409 int lineX = size.
x / 2 - radius;
410 int lineY = size.
y / 2 - radius;
415 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
424 fprintf(
m_file,
"LINE %g %g %g %g\n",
432 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
442 fprintf(
m_file,
"LINE %g %g %g %g\n",
450 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
459 fprintf(
m_file,
"LINE %g %g %g %g\n"
467 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
477 fprintf(
m_file,
"LINE %g %g %g %g\n",
487 case PAD_SHAPE::TRAPEZOID:
491 int ddx =
pad->GetDelta().x / 2;
492 int ddy =
pad->GetDelta().y / 2;
495 poly[0] =
VECTOR2I( -dx + ddy, dy + ddx );
496 poly[1] =
VECTOR2I( dx - ddy, dy - ddx );
497 poly[2] =
VECTOR2I( dx + ddy, -dy + ddx );
498 poly[3] =
VECTOR2I( -dx - ddy, -dy - ddx );
500 for(
int cur = 0; cur < 4; ++cur )
502 int next = ( cur + 1 ) % 4;
503 fprintf(
m_file,
"LINE %g %g %g %g\n",
513 case PAD_SHAPE::CHAMFERED_RECT:
522 pad->GetOrientation(),
523 pad->GetRoundRectCornerRadius(),
524 pad->GetChamferRectRatio(),
525 pad->GetChamferPositions(), 0, maxError,
533 for(
int ii = 0; ii < pointCount; ii++ )
535 int next = ( ii + 1 ) % pointCount;
536 fprintf(
m_file,
"LINE %g %g %g %g\n",
547 case PAD_SHAPE::CUSTOM:
552 pad->MergePrimitivesAsPolygon( &outline );
559 for(
int ii = 0; ii < pointCount; ii++ )
561 int next = ( ii + 1 ) % pointCount;
562 fprintf(
m_file,
"LINE %g %g %g %g\n",
575 fputs(
"\n$ENDPADS\n\n",
m_file );
578 fputs(
"$PADSTACKS\n",
m_file );
581 for(
unsigned i = 0; i < viastacks.size(); i++ )
585 LSET mask =
via->GetLayerSet() & master_layermask;
587 fprintf(
m_file,
"PADSTACK VIA%d.%d.%s %g\n",
588 via->GetWidth(),
via->GetDrillValue(),
594 fprintf(
m_file,
"PAD V%d.%d.%s %s 0 0\n",
595 via->GetWidth(),
via->GetDrillValue(),
606 for(
unsigned i = 1; i < padstacks.size(); i++ )
613 LSET pad_set =
pad->GetLayerSet() & master_layermask;
629 fprintf(
m_file,
"PAD P%u %s 0 0\n", i,
635 fputs(
"$ENDPADSTACKS\n\n",
m_file );
642 size_t ret = 0x11223344;
652 for(
PAD* i : aFootprint->
Pads() )
667 const char* mirror =
"0";
668 std::map<wxString, size_t> shapes;
670 fputs(
"$SHAPES\n",
m_file );
680 wxString shapeName = footprint->GetFPID().Format();
682 auto shapeIt = shapes.find( shapeName );
685 if( shapeIt != shapes.end() )
687 if( modHash != shapeIt->second )
691 wxString newShapeName;
697 newShapeName = wxString::Format( wxT(
"%s_%d" ), shapeName, suffix );
698 shapeIt = shapes.find( newShapeName );
701 while( shapeIt != shapes.end() && shapeIt->second != modHash );
703 shapeName = newShapeName;
706 if( shapeIt != shapes.end() && modHash == shapeIt->second )
717 shapes[shapeName] = modHash;
726 std::set<wxString> pins;
728 for(
PAD*
pad : footprint->Pads() )
734 pinname =
pad->GetNumber();
736 if( pinname.IsEmpty() )
737 pinname = wxT(
"none" );
742 wxString origPinname( pinname );
744 auto it = pins.find( pinname );
746 while( it != pins.end() )
748 pinname = wxString::Format( wxT(
"%s_%d" ), origPinname, suffix );
750 it = pins.find( pinname );
753 pins.insert( pinname );
756 EDA_ANGLE orient =
pad->GetOrientation() - footprint->GetOrientation();
763 "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
764 "PIN \"%s\" PAD%d %g %g %s %g %s\n",
772 fputs(
"$ENDSHAPES\n\n",
m_file );
783 fputs(
"$COMPONENTS\n",
m_file );
791 EDA_ANGLE fp_orient = footprint->GetOrientation();
793 if( footprint->GetFlag() )
805 fprintf(
m_file,
"\nCOMPONENT \"%s\"\n",
807 fprintf(
m_file,
"DEVICE \"DEV_%s\"\n",
809 fprintf(
m_file,
"PLACE %g %g\n",
810 MapXTo( footprint->GetPosition().x ),
811 MapYTo( footprint->GetPosition().y ) );
812 fprintf(
m_file,
"LAYER %s\n",
813 footprint->GetFlag() ?
"BOTTOM" :
"TOP" );
814 fprintf(
m_file,
"ROTATION %g\n",
816 fprintf(
m_file,
"SHAPE \"%s\" %s %s\n",
821 for(
PCB_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
826 fprintf(
m_file,
"TEXT %g %g %g %g %s %s \"%s\"",
830 textItem->GetTextAngle().AsDegrees(),
835 BOX2I textBox = textItem->GetTextBox();
837 fprintf(
m_file,
" 0 0 %g %g\n",
843 fprintf(
m_file,
"SHEET \"RefDes: %s, Value: %s\"\n",
844 TO_UTF8( footprint->GetReference() ),
845 TO_UTF8( footprint->GetValue() ) );
848 fputs(
"$ENDCOMPONENTS\n\n",
m_file );
861 fputs(
"$SIGNALS\n",
m_file );
871 msg.Printf( wxT(
"NoConnection%d" ), NbNoConn++ );
884 for(
PAD*
pad : footprint->Pads() )
889 msg.Printf( wxT(
"NODE \"%s\" \"%s\"" ),
900 fputs(
"$ENDSIGNALS\n\n",
m_file );
908 fputs(
"$HEADER\n",
m_file );
909 fputs(
"GENCAD 1.4\n",
m_file );
920 msg = wxT(
"REVISION \"" ) + rev + wxT(
" " ) + date + wxT(
"\"\n" );
923 fputs(
"UNITS INCH\n",
m_file );
926 msg.Printf( wxT(
"ORIGIN %g %g\n" ),
931 fputs(
"INTERTRACK 0\n",
m_file );
932 fputs(
"$ENDHEADER\n\n",
m_file );
951 int old_netcode, old_width, old_layer;
957 std::sort( tracks.begin(), tracks.end(),
960 if( a->GetNetCode() == b->GetNetCode() )
962 if( a->GetWidth() == b->GetWidth() )
963 return ( a->GetLayer() < b->GetLayer() );
965 return ( a->GetWidth() < b->GetWidth() );
971 fputs(
"$ROUTES\n", m_file );
973 old_netcode = -1; old_width = -1; old_layer = -1;
977 if( old_netcode != track->GetNetCode() )
979 old_netcode = track->GetNetCode();
983 if( net && (net->
GetNetname() != wxEmptyString) )
986 netname = wxT(
"_noname_" );
991 if( old_width != track->GetWidth() )
993 old_width = track->GetWidth();
994 fprintf( m_file,
"TRACK TRACK%d\n", track->GetWidth() );
999 if( old_layer != track->GetLayer() )
1001 old_layer = track->GetLayer();
1002 fprintf( m_file,
"LAYER %s\n",
1006 fprintf( m_file,
"LINE %g %g %g %g\n",
1007 MapXTo( track->GetStart().x ), MapYTo( track->GetStart().y ),
1008 MapXTo( track->GetEnd().x ), MapYTo( track->GetEnd().y ) );
1015 LSET vset =
via->GetLayerSet() & master_layermask;
1017 fprintf( m_file,
"VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1018 via->GetWidth(),
via->GetDrillValue(),
1020 MapXTo(
via->GetStart().x ), MapYTo(
via->GetStart().y ),
1025 fputs(
"$ENDROUTES\n\n", m_file );
1035 std::set<wxString> emitted;
1037 fputs(
"$DEVICES\n",
m_file );
1048 const wxString& shapeName =
shapeNames[componentShape.second];
1050 std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1055 const FOOTPRINT* footprint = componentShape.first;
1058 txt.Printf(
"\nDEVICE \"DEV_%s\"\n",
escapeString( shapeName ) );
1067 for( wxString& item : data )
1070 fputs(
"$ENDDEVICES\n\n",
m_file );
1079 fputs(
"$BOARD\n",
m_file );
1088 fprintf(
m_file,
"LINE %g %g %g %g\n",
1093 fputs(
"$ENDBOARD\n\n",
m_file );
1110 std::set<int> trackinfo;
1113 trackinfo.insert( track->GetWidth() );
1116 fputs(
"$TRACKS\n",
m_file );
1118 for(
int size : trackinfo )
1121 fputs(
"$ENDTRACKS\n\n",
m_file );
1136 fprintf(
m_file,
"INSERT TH\n" );
1138 fprintf(
m_file,
"INSERT SMD\n" );
1147 && ( item->GetLayer() ==
F_SilkS || item->GetLayer() ==
B_SilkS ) )
1160 case SHAPE_T::SEGMENT:
1161 fprintf(
m_file,
"LINE %g %g %g %g\n",
1168 case SHAPE_T::RECTANGLE:
1169 fprintf(
m_file,
"LINE %g %g %g %g\n",
1174 fprintf(
m_file,
"LINE %g %g %g %g\n",
1179 fprintf(
m_file,
"LINE %g %g %g %g\n",
1184 fprintf(
m_file,
"LINE %g %g %g %g\n",
1191 case SHAPE_T::CIRCLE:
1195 fprintf(
m_file,
"CIRCLE %g %g %g\n",
1204 std::swap( start, end );
1206 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
1220 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.
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...
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false, bool aIncludeHiddenText=false) const
Calculate the bounding box containing all board items (or board edge segments).
const std::vector< PAD * > GetPads() const
Return a reference to a list of all the pads.
TITLE_BLOCK & GetTitleBlock()
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
size_type GetHeight() const
size_type GetWidth() 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(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.
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.
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)
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 PCB_LAYER_ID gc_seq[]
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)
constexpr ret_type KiROUND(fp_type v, bool aQuiet=false)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< int32_t > VECTOR2I