44        else if( aId == 
B_Cu )
 
   47            return StrPrintf( 
"INNER%d", aCuCount - aId - 1 );
 
   60        case B_Adhes:   txt = 
"B.Adhes";                
break;
 
   61        case F_Adhes:   txt = 
"F.Adhes";                
break;
 
   62        case B_Paste:   txt = 
"SOLDERPASTE_BOTTOM";     
break;
 
   63        case F_Paste:   txt = 
"SOLDERPASTE_TOP";        
break;
 
   64        case B_SilkS:   txt = 
"SILKSCREEN_BOTTOM";      
break;
 
   65        case F_SilkS:   txt = 
"SILKSCREEN_TOP";         
break;
 
   66        case B_Mask:    txt = 
"SOLDERMASK_BOTTOM";      
break;
 
   67        case F_Mask:    txt = 
"SOLDERMASK_TOP";         
break;
 
   75        case Margin:    txt = 
"Margin";                 
break;
 
   78        case F_CrtYd:   txt = 
"F_CrtYd";                
break;
 
   79        case B_CrtYd:   txt = 
"B_CrtYd";                
break;
 
   80        case F_Fab:     txt = 
"F_Fab";                  
break;
 
   81        case B_Fab:     txt = 
"B_Fab";                  
break;
 
   84            wxASSERT_MSG( 0, wxT( 
"aId UNEXPECTED" ) );
 
   85                        txt = 
"BAD-INDEX!";             
break;
 
 
   96    if( 1<= aId && aId <= 14 )
 
 
  105    wxString 
copy( aString );
 
  106    copy.Replace( wxT( 
"\"" ), wxT( 
"\\\"" ) );
 
 
  114    retv.erase( 0, retv.find_first_not_of( 
'0' ) );
 
 
  126    static const wxString invalid( 
"invalid" );
 
  134    auto itName = 
shapeNames.find( itShape->second );
 
  135    wxCHECK( itName != 
shapeNames.end(), invalid );
 
  137    return itName->second;
 
 
  162    m_file = wxFopen( aFullFileName, wxT( 
"wt" ) );
 
  181        footprint->SetFlag( 0 );
 
  183        if( footprint->GetLayer() == 
B_Cu )
 
  186            footprint->SetFlag( 1 );
 
  225        if( footprint->GetFlag() )
 
  228            footprint->SetFlag( 0 );
 
 
  258    fmt::print( 
m_file, 
"$ARTWORKS\n" );
 
  259    fmt::print( 
m_file, 
"$ENDARTWORKS\n\n" );
 
 
  268    std::vector<PAD*>     padstacks;
 
  269    std::vector<PCB_VIA*> vias;
 
  270    std::vector<PCB_VIA*> viastacks;
 
  272    padstacks.resize( 1 ); 
 
  274    LSEQ gc_seq = 
m_board->GetEnabledLayers().CuStack();
 
  275    std::reverse(gc_seq.begin(), gc_seq.end());
 
  278    LSET    master_layermask = 
m_board->GetDesignSettings().GetEnabledLayers();
 
  279    int     cu_count = 
m_board->GetCopperLayerCount();
 
  281    fmt::print( 
m_file, 
"$PADS\n" );
 
  284    std::vector<PAD*> pads = 
m_board->GetPads();
 
  285    std::sort( pads.begin(), pads.end(), []( 
const PAD* a, 
const PAD* b )
 
  287                                             return PAD::Compare( a, b ) < 0;
 
  294            vias.push_back( 
via );
 
  297    std::sort( vias.begin(), vias.end(), 
viaSort );
 
  298    vias.erase( std::unique( vias.begin(), vias.end(), []( 
const PCB_VIA* a, 
const PCB_VIA* b )
 
  300                                                           return viaSort( a, b ) == false;
 
  307        viastacks.push_back( 
via );
 
  308        fmt::print( 
m_file, 
"PAD V{}.{}.{} ROUND {}\nCIRCLE 0 0 {}\n",
 
  310                    via->GetDrillValue(),
 
  311                    fmt_mask( 
via->GetLayerSet() & master_layermask ).c_str(),
 
  317    PAD* old_pad = 
nullptr;
 
  318    int  pad_name_number = 0;
 
  320    for( 
unsigned i = 0; i<pads.size(); ++i )
 
  325        pad->SetSubRatsnest( pad_name_number );
 
  335        pad->SetSubRatsnest( pad_name_number );
 
  337        fmt::print( 
m_file, 
"PAD P{}", 
pad->GetSubRatsnest() );
 
  339        padstacks.push_back( 
pad ); 
 
  350            fmt::print( 
m_file, 
" ROUND {}\n",
 
  354            fmt::print( 
m_file, 
"CIRCLE {} {} {}\n",
 
  361            fmt::print( 
m_file, 
" RECTANGULAR {}\n",
 
  365            fmt::print( 
m_file, 
"RECTANGLE {} {} {} {}\n",
 
  375            int radius = std::min( size.
x, size.
y ) / 2;
 
  382            int lineX = size.
x / 2 - 
radius;
 
  383            int lineY = size.
y / 2 - 
radius;
 
  388            fmt::print( 
m_file, 
"ARC {} {} {} {} {} {}\n",
 
  399                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  407            fmt::print( 
m_file, 
"ARC {} {} {} {} {} {}\n",
 
  418                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  426            fmt::print( 
m_file, 
"ARC {} {} {} {} {} {}\n",
 
  437                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  445            fmt::print( 
m_file, 
"ARC {} {} {} {} {} {}\n",
 
  456                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  474            poly[0] = 
VECTOR2I( -dx + ddy, dy + ddx );
 
  475            poly[1] = 
VECTOR2I( dx - ddy, dy - ddx );
 
  476            poly[2] = 
VECTOR2I( dx + ddy, -dy + ddx );
 
  477            poly[3] = 
VECTOR2I( -dx - ddy, -dy - ddx );
 
  479            for( 
int cur = 0; cur < 4; ++cur )
 
  481                int next = ( cur + 1 ) % 4;
 
  482                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  501                                                  pad->GetOrientation(),
 
  512                for( 
int ii = 0; ii < pointCount; ii++ )
 
  514                    int next = ( ii + 1 ) % pointCount;
 
  515                    fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  531            pad->MergePrimitivesAsPolygon( 
F_Cu, &outline );
 
  538                for( 
int ii = 0; ii < pointCount; ii++ )
 
  540                    int next = ( ii + 1 ) % pointCount;
 
  541                    fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
  554    fmt::print( 
m_file, 
"\n$ENDPADS\n\n" );
 
  557    fmt::print( 
m_file, 
"$PADSTACKS\n" );
 
  560    for( 
unsigned i = 0; i < viastacks.size(); i++ )
 
  564        LSET mask = 
via->GetLayerSet() & master_layermask;
 
  566        fmt::print( 
m_file, 
"PADSTACK VIA{}.{}.{} {}\n",
 
  568                    via->GetDrillValue(),
 
  574            fmt::print( 
m_file, 
"PAD V{}.{}.{} {} 0 0\n",
 
  576                        via->GetDrillValue(),
 
  587    for( 
unsigned i = 1; i < padstacks.size(); i++ )
 
  592        fmt::print( 
m_file, 
"PADSTACK PAD{} {}\n",
 
  596        LSET pad_set = 
pad->GetLayerSet() & master_layermask;
 
  601            fmt::print( 
m_file, 
"PAD P{} {} 0 0\n",
 
  609            fmt::print( 
m_file, 
"PADSTACK PAD{}F {}\n",
 
  616                fmt::print( 
m_file, 
"PAD P{} {} 0 0\n",
 
  623    fputs( 
"$ENDPADSTACKS\n\n", 
m_file );
 
 
  630    size_t    ret = 0x11223344;
 
  637    for( 
PAD* i : aFootprint->
Pads() )
 
 
  648    const char* mirror = 
"0";
 
  649    std::map<wxString, size_t> shapes;
 
  651    fmt::print( 
m_file, 
"$SHAPES\n" );
 
  661            wxString shapeName = footprint->GetFPID().Format();
 
  663            auto shapeIt = shapes.find( shapeName );
 
  666            if( shapeIt != shapes.end() )
 
  668                if( modHash != shapeIt->second )
 
  672                    wxString newShapeName;
 
  678                        newShapeName = wxString::Format( wxT( 
"%s_%d" ), shapeName, suffix );
 
  679                        shapeIt = shapes.find( newShapeName );
 
  682                    while( shapeIt != shapes.end() && shapeIt->second != modHash );
 
  684                    shapeName = newShapeName;
 
  687                if( shapeIt != shapes.end() && modHash == shapeIt->second )
 
  698            shapes[shapeName] = modHash;
 
  707        std::set<wxString> pins;
 
  709        for( 
PAD* 
pad : footprint->Pads() )
 
  715            pinname = 
pad->GetNumber();
 
  717            if( pinname.IsEmpty() )
 
  718                pinname = wxT( 
"none" );
 
  723                wxString origPinname( pinname );
 
  725                auto it = pins.find( pinname );
 
  727                while( it != pins.end() )
 
  729                    pinname = wxString::Format( wxT( 
"%s_%d" ), origPinname, suffix );
 
  731                    it = pins.find( pinname );
 
  734                pins.insert( pinname );
 
  737            EDA_ANGLE orient = 
pad->GetOrientation() - footprint->GetOrientation();
 
  742            std::string flipStr = ( 
m_flipBottomPads && footprint->GetFlag() ) ? 
"F" : 
"";
 
  746                        "PIN \"{}\" PAD{}{} {} {} {} {} {}\n",
 
  748                        pad->GetSubRatsnest(),
 
  758    fmt::print( 
m_file, 
"$ENDSHAPES\n\n" );
 
 
  764    fmt::print( 
m_file, 
"$COMPONENTS\n" );
 
  766    int cu_count = 
m_board->GetCopperLayerCount();
 
  772        EDA_ANGLE     fp_orient = footprint->GetOrientation();
 
  774        if( footprint->GetFlag() )
 
  786        fmt::print( 
m_file, 
"\nCOMPONENT \"{}\"\n",
 
  788        fmt::print( 
m_file, 
"DEVICE \"DEV_{}\"\n",
 
  790        fmt::print( 
m_file, 
"PLACE {} {}\n",
 
  791                    mapXTo( footprint->GetPosition().x ),
 
  792                    mapYTo( footprint->GetPosition().y ) );
 
  793        fmt::print( 
m_file, 
"LAYER {}\n",
 
  794                    footprint->GetFlag() ? 
"BOTTOM" : 
"TOP" );
 
  795        fmt::print( 
m_file, 
"ROTATION {}\n",
 
  797        fmt::print( 
m_file, 
"SHAPE \"{}\" {} {}\n",
 
  802        for( 
PCB_TEXT* textItem : { &footprint->Reference(), &footprint->Value() } )
 
  806            fmt::print( 
m_file, 
"TEXT {} {} {} {} {} {} \"{}\"",
 
  810                        textItem->GetTextAngle().AsDegrees(),
 
  815            BOX2I textBox = textItem->GetTextBox( 
nullptr );
 
  817            fmt::print( 
m_file, 
" 0 0 {} {}\n",
 
  823        fmt::print( 
m_file, 
"SHEET \"RefDes: {}, Value: {}\"\n",
 
  824                    TO_UTF8( footprint->GetReference() ),
 
  825                    TO_UTF8( footprint->GetValue() ) );
 
  828    fmt::print( 
m_file, 
"$ENDCOMPONENTS\n\n" );
 
 
  841    fmt::print( 
m_file, 
"$SIGNALS\n" );
 
  843    for( 
unsigned ii = 0; ii < 
m_board->GetNetCount(); ii++ )
 
  851                msg.Printf( wxT( 
"NoConnection%d" ), NbNoConn++ );
 
  860            fmt::print( 
m_file, 
"\n" );
 
  864                for( 
PAD* 
pad : footprint->Pads() )
 
  869                    msg.Printf( wxT( 
"NODE \"%s\" \"%s\"" ),
 
  874                    fmt::print( 
m_file, 
"\n" );
 
  880    fmt::print( 
m_file, 
"$ENDSIGNALS\n\n" );
 
 
  886    fmt::print( 
m_file, 
"$HEADER\n" );
 
  887    fmt::print( 
m_file, 
"GENCAD 1.4\n" );
 
  892    fmt::print( 
m_file, 
"DRAWING \"{}\"\n", 
m_board->GetFileName() );
 
  897    fmt::print( 
m_file, 
"REVISION \"{} {}\"\n", rev, date );
 
  898    fmt::print( 
m_file, 
"UNITS INCH\n" );
 
  904    fmt::print( 
m_file, 
"INTERTRACK 0\n" );
 
  905    fmt::print( 
m_file, 
"$ENDHEADER\n\n" );
 
 
  914    int     old_netcode, old_width, old_layer;
 
  915    LSET    master_layermask = 
m_board->GetDesignSettings().GetEnabledLayers();
 
  916    int     cu_count = 
m_board->GetCopperLayerCount();
 
  919    std::sort( tracks.begin(), tracks.end(),
 
  925                   if( a->Type() == PCB_VIA_T )
 
  926                       widthA = static_cast<const PCB_VIA*>( a )->GetWidth( PADSTACK::ALL_LAYERS );
 
  928                       widthA = a->GetWidth();
 
  930                   if( b->Type() == PCB_VIA_T )
 
  931                       widthB = static_cast<const PCB_VIA*>( b )->GetWidth( PADSTACK::ALL_LAYERS );
 
  933                       widthB = b->GetWidth();
 
  935                   if( a->GetNetCode() == b->GetNetCode() )
 
  937                       if( widthA == widthB )
 
  938                           return ( a->GetLayer() < b->GetLayer() );
 
  940                       return ( widthA < widthB );
 
  946    fmt::print( m_file, 
"$ROUTES\n" );
 
  954        if( old_netcode != track->GetNetCode() )
 
  956            old_netcode = track->GetNetCode();
 
  960            if( net && (net->
GetNetname() != wxEmptyString) )
 
  963                netname = wxT( 
"_noname_" );
 
  968        int currentWidth = 0;
 
  975        if( old_width != currentWidth )
 
  977            old_width = currentWidth;
 
  978            fmt::print( m_file, 
"TRACK TRACK{}\n", currentWidth );
 
  983            if( old_layer != track->GetLayer() )
 
  985                old_layer = track->GetLayer();
 
  986                fmt::print( m_file, 
"LAYER {}\n",
 
  990            fmt::print( m_file, 
"LINE {} {} {} {}\n",
 
  991                        mapXTo( track->GetStart().x ), mapYTo( track->GetStart().y ),
 
  992                        mapXTo( track->GetEnd().x ), mapYTo( track->GetEnd().y ) );
 
  996            if( old_layer != track->GetLayer() )
 
  998                old_layer = track->GetLayer();
 
  999                fmt::print( m_file, 
"LAYER {}\n",
 
 1003            VECTOR2I start = track->GetStart();
 
 1010                std::swap( start, 
end );
 
 1014            fmt::print( m_file, 
"ARC {} {} {} {} {} {}\n",
 
 1015                        mapXTo( start.
x ), mapYTo( start.
y ),
 
 1016                        mapXTo( 
end.x ), mapYTo( 
end.y ),
 
 1023            LSET vset = 
via->GetLayerSet() & master_layermask;
 
 1025            fmt::print( m_file, 
"VIA VIA{}.{}.{} {} {} ALL {} via{}\n",
 
 1027                        via->GetDrillValue(),
 
 1029                        mapXTo( 
via->GetStart().x ), mapYTo( 
via->GetStart().y ),
 
 1035    fmt::print( m_file, 
"$ENDROUTES\n\n" );
 
 
 1041    std::set<wxString> emitted;
 
 1043    fmt::print( 
m_file, 
"$DEVICES\n" );
 
 1054        const wxString& shapeName = 
shapeNames[componentShape.second];
 
 1056        std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
 
 1061        const FOOTPRINT* footprint = componentShape.first;
 
 1064        txt.Printf( 
"\nDEVICE \"DEV_%s\"\n", 
escapeString( shapeName ) );
 
 1073    for( wxString& item : data )
 
 1076    fmt::print( 
m_file, 
"$ENDDEVICES\n\n" );
 
 
 1084    fmt::print( 
m_file, 
"$BOARD\n" );
 
 1088    m_board->GetBoardPolygonOutlines( outline );
 
 1093        fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
 1098    fmt::print( 
m_file, 
"$ENDBOARD\n\n" );
 
 
 1105    std::set<int> trackinfo;
 
 1112        trackinfo.insert( track->GetWidth() );
 
 1116    fmt::print( 
m_file, 
"$TRACKS\n" );
 
 1118    for( 
int size : trackinfo )
 
 1121    fmt::print( 
m_file, 
"$ENDTRACKS\n\n" );
 
 
 1131        fmt::print( 
m_file, 
"INSERT TH\n" );
 
 1133        fmt::print( 
m_file, 
"INSERT SMD\n" );
 
 1155                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
 1163                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
 1168                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
 1173                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
 1178                fmt::print( 
m_file, 
"LINE {} {} {} {}\n",
 
 1189                fmt::print( 
m_file, 
"CIRCLE {} {} {}\n",
 
 1198                    std::swap( start, 
end );
 
 1200                fmt::print( 
m_file, 
"ARC {} {} {} {} {} {}\n",
 
 1214                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.
 
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.
 
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
 
const FOOTPRINTS & Footprints() 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.
 
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
 
LSET is a set of PCB_LAYER_IDs.
 
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
 
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
 
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.
 
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)
 
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
 
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
 
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 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)
 
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
 
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)
 
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
 
VECTOR2< int32_t > VECTOR2I