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(
"\\\"" ) );
113 retv.erase( 0, retv.find_first_not_of(
'0' ) );
125 static const wxString invalid(
"invalid" );
133 auto itName =
shapeNames.find( itShape->second );
134 wxCHECK( itName !=
shapeNames.end(), invalid );
136 return itName->second;
161 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 );
279 std::sort( pads.begin(), pads.end(), [](
const PAD* a,
const PAD* b )
281 return PAD::Compare( a, b ) < 0;
287 if(
PCB_VIA*
via = dyn_cast<PCB_VIA*>( track ) )
288 vias.push_back(
via );
291 std::sort( vias.begin(), vias.end(),
viaSort );
292 vias.erase( std::unique( vias.begin(), vias.end(), [](
const PCB_VIA* a,
const PCB_VIA* b )
294 return viaSort( a, b ) == false;
301 viastacks.push_back(
via );
302 fprintf(
m_file,
"PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
304 fmt_mask(
via->GetLayerSet() & master_layermask ).c_str(),
310 PAD* old_pad =
nullptr;
311 int pad_name_number = 0;
313 for(
unsigned i = 0; i<pads.size(); ++i )
318 pad->SetSubRatsnest( pad_name_number );
328 pad->SetSubRatsnest( pad_name_number );
330 fprintf(
m_file,
"PAD P%d",
pad->GetSubRatsnest() );
332 padstacks.push_back(
pad );
342 case PAD_SHAPE::CIRCLE:
343 fprintf(
m_file,
" ROUND %g\n",
347 fprintf(
m_file,
"CIRCLE %g %g %g\n",
353 case PAD_SHAPE::RECTANGLE:
354 fprintf(
m_file,
" RECTANGULAR %g\n",
358 fprintf(
m_file,
"RECTANGLE %g %g %g %g\n",
364 case PAD_SHAPE::ROUNDRECT:
365 case PAD_SHAPE::OVAL:
368 int radius = std::min( size.
x, size.
y ) / 2;
375 int lineX = size.
x / 2 -
radius;
376 int lineY = size.
y / 2 -
radius;
381 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
390 fprintf(
m_file,
"LINE %g %g %g %g\n",
398 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
408 fprintf(
m_file,
"LINE %g %g %g %g\n",
416 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
425 fprintf(
m_file,
"LINE %g %g %g %g\n",
433 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
443 fprintf(
m_file,
"LINE %g %g %g %g\n",
453 case PAD_SHAPE::TRAPEZOID:
461 poly[0] =
VECTOR2I( -dx + ddy, dy + ddx );
462 poly[1] =
VECTOR2I( dx - ddy, dy - ddx );
463 poly[2] =
VECTOR2I( dx + ddy, -dy + ddx );
464 poly[3] =
VECTOR2I( -dx - ddy, -dy - ddx );
466 for(
int cur = 0; cur < 4; ++cur )
468 int next = ( cur + 1 ) % 4;
469 fprintf(
m_file,
"LINE %g %g %g %g\n",
479 case PAD_SHAPE::CHAMFERED_RECT:
489 pad->GetOrientation(),
500 for(
int ii = 0; ii < pointCount; ii++ )
502 int next = ( ii + 1 ) % pointCount;
503 fprintf(
m_file,
"LINE %g %g %g %g\n",
514 case PAD_SHAPE::CUSTOM:
519 pad->MergePrimitivesAsPolygon(
F_Cu, &outline );
526 for(
int ii = 0; ii < pointCount; ii++ )
528 int next = ( ii + 1 ) % pointCount;
529 fprintf(
m_file,
"LINE %g %g %g %g\n",
542 fputs(
"\n$ENDPADS\n\n",
m_file );
545 fputs(
"$PADSTACKS\n",
m_file );
548 for(
unsigned i = 0; i < viastacks.size(); i++ )
552 LSET mask =
via->GetLayerSet() & master_layermask;
554 fprintf(
m_file,
"PADSTACK VIA%d.%d.%s %g\n",
556 via->GetDrillValue(),
562 fprintf(
m_file,
"PAD V%d.%d.%s %s 0 0\n",
564 via->GetDrillValue(),
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;
618 for(
PAD* i : aFootprint->
Pads() )
629 const char* mirror =
"0";
630 std::map<wxString, size_t> shapes;
632 fputs(
"$SHAPES\n",
m_file );
642 wxString shapeName = footprint->GetFPID().Format();
644 auto shapeIt = shapes.find( shapeName );
647 if( shapeIt != shapes.end() )
649 if( modHash != shapeIt->second )
653 wxString newShapeName;
659 newShapeName = wxString::Format( wxT(
"%s_%d" ), shapeName, suffix );
660 shapeIt = shapes.find( newShapeName );
663 while( shapeIt != shapes.end() && shapeIt->second != modHash );
665 shapeName = newShapeName;
668 if( shapeIt != shapes.end() && modHash == shapeIt->second )
679 shapes[shapeName] = modHash;
688 std::set<wxString> pins;
690 for(
PAD*
pad : footprint->Pads() )
696 pinname =
pad->GetNumber();
698 if( pinname.IsEmpty() )
699 pinname = wxT(
"none" );
704 wxString origPinname( pinname );
706 auto it = pins.find( pinname );
708 while( it != pins.end() )
710 pinname = wxString::Format( wxT(
"%s_%d" ), origPinname, suffix );
712 it = pins.find( pinname );
715 pins.insert( pinname );
718 EDA_ANGLE orient =
pad->GetOrientation() - footprint->GetOrientation();
725 "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
726 "PIN \"%s\" PAD%d %g %g %s %g %s\n",
734 fputs(
"$ENDSHAPES\n\n",
m_file );
740 fputs(
"$COMPONENTS\n",
m_file );
748 EDA_ANGLE fp_orient = footprint->GetOrientation();
750 if( footprint->GetFlag() )
762 fprintf(
m_file,
"\nCOMPONENT \"%s\"\n",
764 fprintf(
m_file,
"DEVICE \"DEV_%s\"\n",
766 fprintf(
m_file,
"PLACE %g %g\n",
767 mapXTo( footprint->GetPosition().x ),
768 mapYTo( footprint->GetPosition().y ) );
769 fprintf(
m_file,
"LAYER %s\n",
770 footprint->GetFlag() ?
"BOTTOM" :
"TOP" );
771 fprintf(
m_file,
"ROTATION %g\n",
773 fprintf(
m_file,
"SHAPE \"%s\" %s %s\n",
778 for(
PCB_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
782 fprintf(
m_file,
"TEXT %g %g %g %g %s %s \"%s\"",
786 textItem->GetTextAngle().AsDegrees(),
791 BOX2I textBox = textItem->GetTextBox();
793 fprintf(
m_file,
" 0 0 %g %g\n",
799 fprintf(
m_file,
"SHEET \"RefDes: %s, Value: %s\"\n",
800 TO_UTF8( footprint->GetReference() ),
801 TO_UTF8( footprint->GetValue() ) );
804 fputs(
"$ENDCOMPONENTS\n\n",
m_file );
817 fputs(
"$SIGNALS\n",
m_file );
827 msg.Printf( wxT(
"NoConnection%d" ), NbNoConn++ );
840 for(
PAD*
pad : footprint->Pads() )
845 msg.Printf( wxT(
"NODE \"%s\" \"%s\"" ),
856 fputs(
"$ENDSIGNALS\n\n",
m_file );
864 fputs(
"$HEADER\n",
m_file );
865 fputs(
"GENCAD 1.4\n",
m_file );
876 msg = wxT(
"REVISION \"" ) + rev + wxT(
" " ) + date + wxT(
"\"\n" );
879 fputs(
"UNITS INCH\n",
m_file );
882 msg.Printf( wxT(
"ORIGIN %g %g\n" ),
887 fputs(
"INTERTRACK 0\n",
m_file );
888 fputs(
"$ENDHEADER\n\n",
m_file );
897 int old_netcode, old_width, old_layer;
902 std::sort( tracks.begin(), tracks.end(),
908 if( a->Type() == PCB_VIA_T )
909 widthA = static_cast<const PCB_VIA*>( a )->GetWidth( PADSTACK::ALL_LAYERS );
911 widthA = a->GetWidth();
913 if( b->Type() == PCB_VIA_T )
914 widthB = static_cast<const PCB_VIA*>( b )->GetWidth( PADSTACK::ALL_LAYERS );
916 widthB = b->GetWidth();
918 if( a->GetNetCode() == b->GetNetCode() )
920 if( widthA == widthB )
921 return ( a->GetLayer() < b->GetLayer() );
923 return ( widthA < widthB );
929 fputs(
"$ROUTES\n", m_file );
937 if( old_netcode != track->GetNetCode() )
939 old_netcode = track->GetNetCode();
943 if( net && (net->
GetNetname() != wxEmptyString) )
946 netname = wxT(
"_noname_" );
951 int currentWidth = 0;
958 if( old_width != currentWidth )
960 old_width = currentWidth;
961 fprintf( m_file,
"TRACK TRACK%d\n", currentWidth );
966 if( old_layer != track->GetLayer() )
968 old_layer = track->GetLayer();
969 fprintf( m_file,
"LAYER %s\n",
973 fprintf( m_file,
"LINE %g %g %g %g\n",
974 mapXTo( track->GetStart().x ), mapYTo( track->GetStart().y ),
975 mapXTo( track->GetEnd().x ), mapYTo( track->GetEnd().y ) );
986 std::swap( start,
end );
990 fprintf( m_file,
"ARC %g %g %g %g %g %g\n",
991 mapXTo( start.
x ), mapYTo( start.
y ),
1001 fprintf( m_file,
"VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
1004 mapXTo(
via->GetStart().x ), mapYTo(
via->GetStart().y ),
1009 fputs(
"$ENDROUTES\n\n", m_file );
1015 std::set<wxString> emitted;
1017 fputs(
"$DEVICES\n",
m_file );
1028 const wxString& shapeName =
shapeNames[componentShape.second];
1030 std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
1035 const FOOTPRINT* footprint = componentShape.first;
1038 txt.Printf(
"\nDEVICE \"DEV_%s\"\n",
escapeString( shapeName ) );
1047 for( wxString& item : data )
1050 fputs(
"$ENDDEVICES\n\n",
m_file );
1058 fputs(
"$BOARD\n",
m_file );
1067 fprintf(
m_file,
"LINE %g %g %g %g\n",
1072 fputs(
"$ENDBOARD\n\n",
m_file );
1079 std::set<int> trackinfo;
1086 trackinfo.insert( track->GetWidth() );
1090 fputs(
"$TRACKS\n",
m_file );
1092 for(
int size : trackinfo )
1095 fputs(
"$ENDTRACKS\n\n",
m_file );
1105 fprintf(
m_file,
"INSERT TH\n" );
1107 fprintf(
m_file,
"INSERT SMD\n" );
1128 case SHAPE_T::SEGMENT:
1129 fprintf(
m_file,
"LINE %g %g %g %g\n",
1136 case SHAPE_T::RECTANGLE:
1137 fprintf(
m_file,
"LINE %g %g %g %g\n",
1142 fprintf(
m_file,
"LINE %g %g %g %g\n",
1147 fprintf(
m_file,
"LINE %g %g %g %g\n",
1152 fprintf(
m_file,
"LINE %g %g %g %g\n",
1159 case SHAPE_T::CIRCLE:
1163 fprintf(
m_file,
"CIRCLE %g %g %g\n",
1172 std::swap( start,
end );
1174 fprintf(
m_file,
"ARC %g %g %g %g %g %g\n",
1188 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.
std::string FmtBin() const
Return a binary string showing contents of this set.
const 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.
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
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
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 createRoutesSection()
Create the $ROUTES section.
void createTracksInfoData()
Create the "$TRACKS" section.
void createShapesSection()
Create the footprint shape list.
const wxString getShapeName(FOOTPRINT *aFootprint)
void createDevicesSection()
Create the $DEVICES section.
bool createHeaderInfoData()
Creates the header section.
double mapXTo(int aX)
Helper functions to calculate coordinates of footprints in GenCAD values.
void createArtworksSection()
void createBoardSection()
void footprintWriteShape(FOOTPRINT *aFootprint, const wxString &aShapeName)
Create the shape of a footprint (SHAPE section)
void createPadsShapesSection()
bool m_useIndividualShapes
void createSignalsSection()
bool WriteFile(const wxString &aFullFileName)
Export a GenCAD file.
void createComponentsSection()
Create the $COMPONENTS GenCAD section.
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.
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.
EDA_ANGLE GetAngle() const
virtual VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
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::string genCADLayerNameFlipped(int aCuCount, PCB_LAYER_ID aId)
The flipped layer name for GenCAD export (to make CAM350 imports correct).
static std::map< int, wxString > shapeNames
static std::string genCADLayerName(int aCuCount, PCB_LAYER_ID aId)
Layer names for GenCAD export.
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::map< FOOTPRINT *, int > componentShapes
Association between shape names (using shapeName index) and components.
static std::string fmt_mask(const LSET &aSet)
static bool viaSort(const PCB_VIA *aPadref, const PCB_VIA *aPadcmp)
Sort vias for uniqueness.
static wxString escapeString(const wxString &aString)
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Hashing functions for EDA_ITEMs.
@ REL_COORD
Use coordinates relative to the parent object.
bool IsCopperLayer(int aLayerId)
Test 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_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I