47#include <wx/numformatter.h>
48#include <wx/xml/xml.h>
76 std::vector<FOOTPRINT*> retval;
79 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
89 if( aParent->GetChildren() )
90 aNode->SetNext( aParent->GetChildren() );
92 aNode->SetNext(
nullptr );
94 aParent->SetChildren( aNode );
95 aNode->SetParent( aParent );
104 aNode->SetNext( aPrev->GetNext() );
105 aPrev->SetNext( aNode );
106 aNode->SetParent( aPrev->GetParent() );
115 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
127 static wxXmlNode* lastNode =
nullptr;
129 if( lastNode && lastNode->GetParent() == aParent && lastNode->GetNext() ==
nullptr )
131 aNode->SetParent( aParent );
132 lastNode->SetNext( aNode );
136 aParent->AddChild( aNode );
148 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
159 wxString key = aPrefix ? wxString( aPrefix ) + wxT(
":" ) + aStr : aStr;
171 str.Replace( wxT(
":" ), wxT(
"_" ) );
175 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
185 wxString
name = base;
189 name = wxString::Format(
"%s_%d", base, suffix++ );
205 const char* aPrefix )
const
207 return genString( wxString::Format( wxS(
"%s_%s" ),
209 m_board->GetLayerName( aBottom ) ), aPrefix );
220 if(
name.empty() && fp )
224 if( fp->
Pads()[ii] == aPad )
232 name = wxString::Format(
"NPTH%zu", ii );
233 else if(
name.empty() )
234 name = wxString::Format(
"PAD%zu", ii );
243 [&](
const wxString& aName )
262 wxString
name = baseName;
265 while( !tryInsert(
name ) )
266 name = wxString::Format(
"%s_%d", baseName, suffix++ );
276 wxString str = wxString::FromCDouble( aVal, aSigFig == -1 ?
m_sigfig : aSigFig );
279 while( str.EndsWith( wxT(
"00" ) ) )
283 if( str == wxT(
"-0.0" ) )
308 aNode->AddAttribute( aName, aValue );
314 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
316 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
317 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
318 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
323 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
328 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
333 return xmlHeaderNode;
345 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
353 wxFileName fn(
m_board->GetFileName() );
360 contentNode->AddChild( color_node );
364 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
384 contentNode->AddChild( color_node );
393 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
468 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
472 wxString layer_name = item->GetLayerName();
473 int sub_layer_count = 1;
475 if( layer_name.empty() )
476 layer_name =
m_board->GetLayerName( item->GetBrdLayerId() );
478 layer_name =
genString( layer_name,
"LAYER" );
482 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
484 sub_layer_count = item->GetSublayersCount();
491 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
493 wxString sub_layer_name = layer_name;
496 sub_layer_name += wxString::Format(
"_%d", sub_idx );
498 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
504 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
508 wxString colorName = item->GetColor( sub_idx );
510 if( colorName.StartsWith( wxT(
"#" ) ) )
513 COLOR4D layer_color( colorName );
525 if( fab_color.GetName() == colorName )
549 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
555 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
556 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
563 wxCHECK_RET( aNode,
"aNode is null" );
568 wxXmlNode* entry_node =
nullptr;
572 size_t hash =
lineHash( aWidth, aDashType );
573 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
577 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
592 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
639 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
641 std::list<VECTOR2I> pts;
649 wxXmlNode* line_node =
nullptr;
656 addXY( line_node, pts.front(),
"startX",
"startY" );
657 addXY( line_node, pts.back(),
"endX",
"endY" );
661 line_node =
appendNode( text_node,
"Polyline" );
662 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
663 addXY( point_node, pts.front() );
665 auto iter = pts.begin();
667 for( ++iter; iter != pts.end(); ++iter )
669 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
670 addXY( point_node, *iter );
685 if( aPt1 == pts.back() )
686 pts.push_back( aPt2 );
687 else if( aPt2 == pts.front() )
688 pts.push_front( aPt1 );
689 else if( aPt1 == pts.front() )
690 pts.push_front( aPt2 );
691 else if( aPt2 == pts.back() )
692 pts.push_back( aPt1 );
696 pts.push_back( aPt1 );
697 pts.push_back( aPt2 );
702 pts.push_back( aPt1 );
703 pts.push_back( aPt2 );
709 if( aPoly.PointCount() < 3 )
712 wxXmlNode* outline_node =
appendNode( text_node,
"Outline" );
713 wxXmlNode* poly_node =
appendNode( outline_node,
"Polygon" );
716 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
717 wxXmlNode* point_node =
appendNode( poly_node,
"PolyBegin" );
718 addXY( point_node, pts.front() );
720 for(
size_t ii = 1; ii < pts.size(); ++ii )
722 wxXmlNode* point_node =
724 addXY( point_node, pts[ii] );
727 point_node =
appendNode( poly_node,
"PolyStepSegment" );
728 addXY( point_node, pts.front() );
739 if( text_node->GetChildren() ==
nullptr )
741 aContentNode->RemoveChild( text_node );
754 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
759 int maxError =
m_board->GetDesignSettings().m_MaxError;
779 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
780 circle_node->AddAttribute(
"diameter",
793 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
809 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
825 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
829 roundrect_node->AddAttribute(
"radius",
847 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
852 int shorterSide = std::min( pad_size.
x, pad_size.
y );
883 int dx = pad_size.
x / 2;
884 int dy = pad_size.
y / 2;
885 int ddx = trap_delta.
x / 2;
886 int ddy = trap_delta.
y / 2;
888 outline.
Append( -dx - ddy, dy + ddx );
889 outline.
Append( dx + ddy, dy - ddx );
890 outline.
Append( dx - ddy, -dy + ddx );
891 outline.
Append( -dx + ddy, -dy - ddx );
933 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
947 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
965 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
967 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
992 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
999 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1016 width += stroke_width;
1017 height += stroke_width;
1039 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1061 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1063 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1080 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1084 std::vector<VECTOR2I> points;
1087 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1088 addXY( point_node, points[0] );
1090 for(
size_t i = 1; i < points.size(); i++ )
1092 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1093 addXY( point_node, points[i] );
1107 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1109 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1126 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1135 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1156 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1164 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1166 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1169 return logisticNode;
1180 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1182 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1184 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1185 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1186 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1189 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1192 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1194 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1195 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1218 m_refdes =
new std::vector<REFDES>();
1219 m_props =
new std::map<wxString, wxString>();
1230 wxString m_OEMDesignRef;
1234 std::vector<REFDES>* m_refdes;
1235 std::map<wxString, wxString>*
m_props;
1238 std::set<std::unique_ptr<struct BOM_ENTRY>,
1239 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1240 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1241 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1242 const std::unique_ptr<struct BOM_ENTRY>& b )
1244 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1249 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1250 fp->SetParentGroup(
nullptr );
1251 fp->SetPosition( {0, 0} );
1252 fp->SetOrientation(
ANGLE_0 );
1259 Report( wxString::Format(
_(
"Footprint %s not found in dictionary; BOM data may be incomplete." ),
1260 fp->GetFPID().GetLibItemName().wx_str() ),
1265 auto entry = std::make_unique<struct BOM_ENTRY>();
1271 entry->m_OEMDesignRef = it->second;
1275 Report( wxString::Format(
_(
"Component \"%s\" missing OEM reference; BOM entry will be skipped." ),
1276 fp->GetFPID().GetLibItemName().wx_str() ),
1280 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1282 entry->m_pads = fp->GetPadCount();
1287 entry->m_type =
"DOCUMENT";
1289 entry->m_type =
"ELECTRICAL";
1291 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1294 ( *bom_iter )->m_count++;
1298 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1302 ( *bom_iter )->m_refdes->push_back( refdes );
1306 for(
PCB_FIELD* prop : fp->GetFields() )
1310 if( prop->IsMandatory() && !prop->IsValue() )
1313 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1317 if( bom_entries.empty() )
1320 wxFileName fn(
m_board->GetFileName() );
1322 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1323 m_xml_root->InsertChild( bomNode, aEcadNode );
1326 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1330 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1333 for(
const auto& entry : bom_entries )
1335 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1336 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1337 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1338 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1339 addAttribute( bomEntryNode,
"category", entry->m_type );
1341 for(
const REFDES& refdes : *( entry->m_refdes ) )
1343 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1346 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1347 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1350 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1351 addAttribute( characteristicsNode,
"category", entry->m_type );
1353 for(
const auto& prop : *( entry->m_props ) )
1355 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1356 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1357 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1358 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1376 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1393 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1394 std::set<PCB_LAYER_ID> added_layers;
1396 for(
int i = 0; i < stackup.
GetCount(); i++ )
1400 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1404 if( ly_name.IsEmpty() )
1413 if( sublayer_id > 0 )
1414 ly_name += wxString::Format(
"_%d", sublayer_id );
1418 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1420 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1422 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1424 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1426 switch ( stackup_item->
GetType() )
1431 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1433 propertyNode =
appendNode( conductorNode,
"Property" );
1434 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1435 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1441 propertyNode =
appendNode( generalNode,
"Property" );
1442 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1444 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1445 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1446 propertyNode =
appendNode( dielectricNode,
"Property" );
1449 dielectricNode =
appendNode( specNode,
"Dielectric" );
1450 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1451 propertyNode =
appendNode( dielectricNode,
"Property" );
1458 propertyNode =
appendNode( generalNode,
"Property" );
1459 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1461 propertyNode =
appendNode( generalNode,
"Property" );
1462 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1467 propertyNode =
appendNode( generalNode,
"Property" );
1468 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1470 propertyNode =
appendNode( generalNode,
"Property" );
1471 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1484 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1526 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1567 aLayer ==
F_Cu ?
"TOP"
1568 : aLayer ==
B_Cu ?
"BOTTOM"
1583 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1584 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1591 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1593 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1594 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1599 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1600 std::set<PCB_LAYER_ID> added_layers;
1602 for(
int i = 0; i < stackup.
GetCount(); i++ )
1606 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1609 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1612 if( ly_name.IsEmpty() )
1621 if( sublayer_id > 0 )
1622 ly_name += wxString::Format(
"_%d", sublayer_id );
1626 ly_name =
genString( ly_name,
"LAYER" );
1628 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1632 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", i ) );
1634 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1635 addAttribute( specLayerNode,
"id", wxString::Format(
"SPEC_%s", ly_name ) );
1648 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1649 std::set<PCB_LAYER_ID> added_layers;
1651 for(
int i = 0; i < stackup.
GetCount(); i++ )
1658 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1660 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1663 if( ly_name.IsEmpty() )
1673 if( sublayer_id > 0 )
1674 ly_name += wxString::Format(
"_%d", sublayer_id );
1678 ly_name =
genString( ly_name,
"LAYER" );
1685 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1687 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1702 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
1711 added_layers.insert( layer );
1712 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1733 for(
PAD*
pad : fp->Pads() )
1735 if(
pad->HasDrilledHole() )
1737 else if(
pad->HasHole() )
1744 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1745 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
1750 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1757 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1758 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
1764 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1780 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
1782 if(
via->Padstack().IsFilled().value_or(
false ) )
1785 if(
via->Padstack().IsCapped().value_or(
false ) )
1790 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
1793 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
1796 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
1800 for(
auto& tuple : new_layers )
1806 bool add_node =
true;
1809 wxString layerFunction;
1812 switch( std::get<0>(layers) )
1816 layerFunction =
"COATINGNONCOND";
1820 layerFunction =
"HOLEFILL";
1824 layerFunction =
"COATINGNONCOND";
1828 layerFunction =
"HOLEFILL";
1832 layerFunction =
"COATINGCOND";
1840 if( add_node && !vec.empty() )
1842 wxXmlNode* node =
appendNode( aCadLayerNode,
"LAYER" );
1856 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
1857 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
1859 if( first_external )
1861 if( second_external )
1868 if( second_external )
1874 wxXmlNode* spanNode =
appendNode( node,
"SPAN" );
1885 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1886 wxFileName fn(
m_board->GetFileName() );
1892 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1912 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1919 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1926 addShape( padNode, *aPad, aLayer );
1930 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1943 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1964 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1971 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1985 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1986 padStackHoleNode->AddAttribute(
"name",
1987 wxString::Format(
"%s%d_%d",
2005 if( !
m_board->IsLayerEnabled( layer ) )
2008 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2010 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2018 addShape( padStackPadDefNode, shape );
2022 addShape( padStackPadDefNode, *aPad, layer );
2034 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2041 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2046 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2049 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2058 bool drill ) ->
void
2063 shape.
SetEnd( {
KiROUND( aVia->GetDrillValue() / 2.0 ), 0 } );
2065 shape.
SetEnd( {
KiROUND( aVia->GetWidth( layer ) / 2.0 ), 0 } );
2067 wxXmlNode* padStackPadDefNode =
2068 appendNode( padStackDefNode,
"PadstackPadDef" );
2070 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2073 addShape( padStackPadDefNode, shape );
2093 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2096 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2099 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2108 wxXmlNode* polygonNode =
nullptr;
2116 polygonNode =
appendNode( aParentNode,
"Polygon" );
2117 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2119 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2120 addXY( polybeginNode, pts[0] );
2122 for(
size_t ii = 1; ii < pts.size(); ++ii )
2124 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2125 addXY( polyNode, pts[ii] );
2128 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2129 addXY( polyendNode, pts[0] );
2140 addLineDesc( polygonNode, aWidth, aDashType,
true );
2144 wxCHECK( aWidth == 0,
false );
2157 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2159 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2161 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2162 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2164 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2165 addXY( polybeginNode, hole[0] );
2167 for(
size_t jj = 1; jj < hole.size(); ++jj )
2169 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2170 addXY( polyNode, hole[jj] );
2173 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2174 addXY( polyendNode, hole[0] );
2187 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2207 outline = &bbox_outline;
2212 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2214 if( !outlineNode->GetChildren() )
2216 aParentNode->RemoveChild( outlineNode );
2233 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2243 aParentNode->RemoveChild( contourNode );
2256 if( !
m_board->GetBoardPolygonOutlines( board_outline ) )
2262 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2266 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2267 aStepNode->RemoveChild( profileNode );
2290 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2291 fp->SetParentGroup(
nullptr );
2292 fp->SetPosition( { 0, 0 } );
2293 fp->SetOrientation(
ANGLE_0 );
2297 fp->GetFPID().GetLibItemName().wx_str(),
2301 addAttribute( aContentNode,
"packageRef", iter->second );
2308 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2309 wxXmlNode* otherSideViewNode =
nullptr;
2315 if( fp->FindPadByNumber(
"1" ) )
2317 else if ( fp->FindPadByNumber(
"A1" ) )
2319 else if ( fp->FindPadByNumber(
"A" ) )
2321 else if ( fp->FindPadByNumber(
"a" ) )
2323 else if ( fp->FindPadByNumber(
"a1" ) )
2325 else if ( fp->FindPadByNumber(
"Anode" ) )
2327 else if ( fp->FindPadByNumber(
"ANODE" ) )
2332 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2344 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2356 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2360 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2362 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2387 elements[item->GetLayer()][is_abs].push_back( item );
2390 auto add_base_node =
2393 wxXmlNode* parent = packageNode;
2398 if( !otherSideViewNode )
2399 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2401 parent = otherSideViewNode;
2407 name =
"SilkScreen";
2408 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2409 name =
"AssemblyDrawing";
2417 auto add_marking_node =
2418 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2420 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2422 return marking_node;
2425 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2426 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2430 if( elements.find( layer ) != elements.end() )
2432 if( elements[layer][
true].size() > 0 )
2433 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2434 else if( elements[layer][
false].size() > 0 )
2435 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2439 for(
auto& [layer, map] : elements )
2441 wxXmlNode* layer_node = add_base_node( layer );
2442 wxXmlNode* marking_node = add_marking_node( layer_node );
2443 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2444 bool update_bbox =
false;
2448 layer_nodes[layer] = layer_node;
2452 for(
auto& [is_abs, vec] : map )
2456 wxXmlNode* output_node =
nullptr;
2459 layer_bbox[layer].Merge( item->GetBoundingBox() );
2462 output_node = add_marking_node( layer_node );
2464 output_node = group_node;
2466 switch( item->Type() )
2472 if(
text->IsKnockout() )
2486 if(
text->IsBorderEnabled() )
2489 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2491 text->GetBorderWidth() );
2512 if( group_node->GetChildren() ==
nullptr )
2514 marking_node->RemoveChild( group_node );
2515 layer_node->RemoveChild( marking_node );
2517 delete marking_node;
2521 for(
auto&[layer, bbox] : layer_bbox )
2523 if( bbox.GetWidth() > 0 )
2525 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2528 std::vector<VECTOR2I> points( 4 );
2529 points[0] = bbox.GetPosition();
2530 points[2] = bbox.GetEnd();
2531 points[1].x = points[0].x;
2532 points[1].y = points[2].y;
2533 points[3].x = points[2].x;
2534 points[3].y = points[0].y;
2536 outline.
Append( points );
2542 std::map<wxString, wxXmlNode*> pin_nodes;
2544 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2546 PAD*
pad = fp->Pads()[ii];
2548 wxXmlNode* pinNode =
nullptr;
2550 auto [ it, inserted ] = pin_nodes.emplace(
name,
nullptr );
2555 it->second = pinNode;
2563 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2564 else if(
pad->IsOnCopperLayer() )
2565 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2567 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2569 if(
pad->HasHole() )
2574 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2576 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2577 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
2579 if( fp->IsFlipped() )
2588 pinNode = it->second;
2606 std::vector<wxXmlNode*> componentNodes;
2607 std::vector<wxXmlNode*> packageNodes;
2608 std::set<wxString> packageNames;
2610 bool generate_unique =
m_OEMRef.empty();
2614 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2616 wxXmlNode* pkg =
addPackage( componentNode, fp );
2619 packageNodes.push_back( pkg );
2625 if( !generate_unique )
2628 if( field && !field->
GetText().empty() )
2634 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2635 fp->GetFPID().GetLibItemName().wx_str(),
2640 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
2648 else if( fp->GetAttributes() &
FP_SMD )
2653 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
2655 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2659 if( fp->IsFlipped() )
2665 if( fp->IsFlipped() )
2669 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2671 componentNodes.push_back( componentNode );
2680 for( wxXmlNode* pkg : packageNodes )
2681 aStepNode->AddChild( pkg );
2683 for( wxXmlNode* cmp : componentNodes )
2684 aStepNode->AddChild( cmp );
2692 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2694 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
2696 for(
auto& [cmp,
pin] : pin_pair )
2698 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2712 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2716 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2718 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
2719 [&layers, &elements](
PCB_TRACK* aTrack )
2721 if( aTrack->Type() == PCB_VIA_T )
2723 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2725 for( PCB_LAYER_ID layer : layers )
2727 if( via->FlashLayer( layer ) )
2728 elements[layer][via->GetNetCode()].push_back( via );
2733 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2737 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2738 [ &elements ](
ZONE* zone )
2740 LSEQ zone_layers = zone->GetLayerSet().Seq();
2742 for( PCB_LAYER_ID layer : zone_layers )
2743 elements[layer][zone->GetNetCode()].push_back( zone );
2746 for(
BOARD_ITEM* item : m_board->Drawings() )
2749 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2751 elements[item->GetLayer()][0].push_back( item );
2754 for(
FOOTPRINT* fp : m_board->Footprints() )
2756 for(
PCB_FIELD* field : fp->GetFields() )
2757 elements[field->GetLayer()][0].push_back( field );
2759 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2760 elements[item->GetLayer()][0].push_back( item );
2762 for(
PAD*
pad : fp->Pads() )
2764 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2768 if(
pad->FlashLayer( layer ) )
2769 elements[layer][
pad->GetNetCode()].push_back(
pad );
2776 if( m_progressReporter )
2777 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2779 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2780 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2782 auto process_net = [&] (
int net )
2784 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
2789 std::stable_sort( vec.begin(), vec.end(),
2792 if( a->GetParentFootprint() == b->GetParentFootprint() )
2793 return a->Type() < b->Type();
2795 return a->GetParentFootprint() < b->GetParentFootprint();
2798 generateLayerSetNet( layerNode, layer, vec );
2803 if( m_progressReporter )
2805 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2806 m_board->GetLayerName( layer ),
2807 net->GetNetname() ) );
2808 m_progressReporter->AdvanceProgress();
2811 process_net( net->GetNetCode() );
2814 if( layerNode->GetChildren() ==
nullptr )
2816 aStepNode->RemoveChild( layerNode );
2829 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2830 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2841 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
2846 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2849 if(
via->GetNetCode() > 0 )
2852 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2853 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2858 addXY( holeNode,
via->GetPosition() );
2867 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
2872 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2875 if(
pad->GetNetCode() > 0 )
2878 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2879 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2885 addXY( holeNode,
pad->GetPosition() );
2894 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2895 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2899 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2901 if(
pad->GetNetCode() > 0 )
2904 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2911 std::vector<BOARD_ITEM*>& aItems )
2913 auto it = aItems.begin();
2914 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2915 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2916 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2918 bool has_via =
false;
2919 bool has_pad =
false;
2921 wxXmlNode* padSetNode =
nullptr;
2923 wxXmlNode* viaSetNode =
nullptr;
2925 wxXmlNode* teardropLayerSetNode =
nullptr;
2926 wxXmlNode* teardropFeatureSetNode =
nullptr;
2928 bool teardrop_warning =
false;
2933 if( item->GetNetCode() > 0 )
2943 shape.
SetStart( track->GetStart() );
2944 shape.
SetEnd( track->GetEnd() );
2945 shape.
SetWidth( track->GetWidth() );
2962 viaSetNode = layerSetNode;
2967 viaSetNode =
appendNode( layerSetNode,
"Set" );
2969 if( track->GetNetCode() > 0 )
2976 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2983 wxXmlNode* zoneFeatureNode = specialNode;
2985 if( zone->IsTeardropArea() )
2989 if( !teardropFeatureSetNode )
2991 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
2992 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
2994 if( zone->GetNetCode() > 0 )
2997 genString( zone->GetNetname(),
"NET" ) );
3000 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3002 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3005 zoneFeatureNode = teardropFeatureSetNode;
3007 else if( !teardrop_warning )
3009 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3011 teardrop_warning =
true;
3018 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3019 wxString refDes =
componentName( zone->GetParentFootprint() );
3021 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3023 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3027 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3029 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3040 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3043 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3045 bool link_to_component =
true;
3048 link_to_component =
false;
3050 if( link_to_component )
3053 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3060 wxXmlNode* xformNode =
appendNode( tempFeature,
"Xform" );
3070 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3072 if( shape->GetNetCode() > 0 )
3075 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3092 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3094 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3099 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3104 bool link_to_component = fp !=
nullptr;
3107 link_to_component =
false;
3109 if( link_to_component )
3112 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3113 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3115 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3117 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3123 addText( tempFeature, text_item,
text->GetFontMetrics() );
3141 padSetNode = layerSetNode;
3146 padSetNode =
appendNode( aLayerNode,
"Set" );
3148 if(
pad->GetNetCode() > 0 )
3163 switch( item->Type() )
3168 add_track(
static_cast<PCB_TRACK*
>( item ) );
3176 add_pad(
static_cast<PAD*
>( item ) );
3180 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3205 if( specialNode->GetChildren() ==
nullptr )
3207 featureSetNode->RemoveChild( specialNode );
3211 if( featureSetNode->GetChildren() ==
nullptr )
3213 layerSetNode->RemoveChild( featureSetNode );
3214 delete featureSetNode;
3217 if( layerSetNode->GetChildren() ==
nullptr )
3219 aLayerNode->RemoveChild( layerSetNode );
3220 delete layerSetNode;
3231 bool add_node =
true;
3237 switch( std::get<0>(layers) )
3266 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3270 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3284 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3286 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3305 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3309 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3312 std::set<wxString> unique_parts;
3313 std::map<wxString,wxString> unique_vendors;
3317 auto [ it, success ] = unique_parts.insert(
name );
3322 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3329 for (
int ii = 0; ii < 2; ++ii )
3335 if( mpn_name.empty() )
3338 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3342 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3345 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3347 wxString
name = wxT(
"UNKNOWN" );
3350 if( !ii && company[ii] )
3358 else if( !ii && !company_name[ii].
empty() )
3360 name = company_name[ii];
3362 else if( ii && !
m_dist.empty() )
3367 auto [vendor_id, inserted] = unique_vendors.emplace(
3369 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3371 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3375 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3391 const std::map<std::string, UTF8>* aProperties )
3398 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3400 if( it->second ==
"inch" )
3407 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3408 m_sigfig = std::stoi( it->second );
3410 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3413 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3416 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3417 m_mpn = it->second.wx_str();
3419 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3420 m_mfg = it->second.wx_str();
3422 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3423 m_dist = it->second.wx_str();
3425 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3430 for(
char c =
'a'; c <=
'z'; ++c )
3433 for(
char c =
'A'; c <=
'Z'; ++c )
3436 for(
char c =
'0'; c <=
'9'; ++c )
3440 std::string specialChars =
"_\\-.+><";
3442 for(
char c : specialChars )
3471 double written_bytes = 0.0;
3472 double last_yield = 0.0;
3479 auto update_progress = [&](
size_t aBytes )
3481 written_bytes += aBytes;
3482 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
3487 if( last_yield + 0.01 < percent )
3489 last_yield = percent;
3503 size_t size = out_stream.GetSize();
constexpr int ARC_HIGH_DEF
constexpr double PCB_IU_PER_MM
Pcbnew IU is 1 nanometer.
bool IsPrmSpecified(const wxString &aPrmValue)
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
wxString GetMajorMinorPatchVersion()
Get the major, minor and patch version in a string major.minor.patch This is extracted by CMake from ...
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsKnockout() const
FOOTPRINT * GetParentFootprint() const
VECTOR2I GetFPRelativePosition() const
Manage one layer needed to make a physical board.
wxString GetTypeName() const
int GetSublayersCount() const
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString GetColor(int aDielectricSubLayer=0) const
wxString GetLayerName() const
PCB_LAYER_ID GetBrdLayerId() const
int GetThickness(int aDielectricSubLayer=0) const
BOARD_STACKUP_ITEM_TYPE GetType() const
wxString GetMaterial(int aDielectricSubLayer=0) const
int GetDielectricLayerId() const
double GetLossTangent(int aDielectricSubLayer=0) const
Manage layers needed to make a physical board.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
int BuildBoardThicknessFromStackup() const
Information pertinent to a Pcbnew printed circuit board.
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
const VECTOR2I & GetBezierC2() const
FILL_T GetFillMode() const
int GetRectangleWidth() const
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void SetEnd(const VECTOR2I &aEnd)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
const VECTOR2I & GetBezierC1() const
int GetRectangleHeight() const
bool IsClockwiseArc() const
void SetWidth(int aWidth)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
const VECTOR2I & GetTextPos() const
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
virtual EDA_ANGLE GetDrawRotation() const
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
const TEXT_ATTRIBUTES & GetAttributes() const
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
static ENUM_MAP< T > & Instance()
wxString m_name
Name of the IO loader.
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
virtual void Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
FONT is an abstract base class for both outline and stroke fonts.
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics) const
Draw a string.
A color representation with 4 components: red, green, blue, alpha.
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.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Handle the data for a net.
Container for NETINFO_ITEM elements, which are the nets.
std::optional< bool > IsFilled() const
std::optional< bool > IsTented(PCB_LAYER_ID aSide) const
Checks if this padstack is tented (covered in soldermask) on the given side.
std::optional< bool > IsPlugged(PCB_LAYER_ID aSide) const
std::optional< bool > IsCapped() const
std::optional< bool > IsCovered(PCB_LAYER_ID aSide) const
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void MergePrimitivesAsPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
int GetDrillSizeY() const
const VECTOR2I & GetDrillSize() const
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
VECTOR2I GetPosition() const override
int GetDrillSizeX() const
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
int GetChamferPositions(PCB_LAYER_ID aLayer) const
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
VECTOR2I GetSolderPasteMargin(PCB_LAYER_ID aLayer) const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
bool HasDrilledHole() const override
bool HasHole() const override
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
const VECTOR2I & GetMid() const
void addText(wxXmlNode *aContentNode, EDA_TEXT *aShape, const KIFONT::METRICS &aFontMetrics)
wxString floatVal(double aVal, int aSigFig=-1) const
void generateLayerSetDrill(wxXmlNode *aStepNode)
wxString genLayerString(PCB_LAYER_ID aLayer, const char *aPrefix) const
wxXmlNode * generateContentSection()
Creates the Content section of the XML file.
wxXmlNode * appendNode(wxXmlNode *aParent, const wxString &aName)
void generateDrillLayers(wxXmlNode *aCadLayerNode)
wxXmlNode * addPackage(wxXmlNode *aStepNode, FOOTPRINT *aFootprint)
void generateComponents(wxXmlNode *aStepNode)
bool addContourNode(wxXmlNode *aParentNode, const SHAPE_POLY_SET &aPolySet, int aOutline=0, FILL_T aFillType=FILL_T::FILLED_SHAPE, int aWidth=0, LINE_STYLE aDashType=LINE_STYLE::SOLID)
wxString componentName(FOOTPRINT *aFootprint)
bool addOutlineNode(wxXmlNode *aParentNode, const SHAPE_POLY_SET &aPolySet, int aWidth=0, LINE_STYLE aDashType=LINE_STYLE::SOLID)
void generateStackup(wxXmlNode *aCadLayerNode)
std::map< std::tuple< auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID >, std::vector< BOARD_ITEM * > > m_auxilliary_Layers
bool addPolygonNode(wxXmlNode *aParentNode, const SHAPE_LINE_CHAIN &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE, int aWidth=0, LINE_STYLE aDashType=LINE_STYLE::SOLID)
void generateLayerSetNet(wxXmlNode *aLayerNode, PCB_LAYER_ID aLayer, std::vector< BOARD_ITEM * > &aItems)
bool isValidLayerFor2581(PCB_LAYER_ID aLayer)
void insertNodeAfter(wxXmlNode *aPrev, wxXmlNode *aNode)
void generateCadLayers(wxXmlNode *aCadLayerNode)
std::vector< wxXmlNode * > m_padstacks
wxString pinName(const PAD *aPad) const
void generateCadSpecs(wxXmlNode *aCadLayerNode)
void addVia(wxXmlNode *aContentNode, const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
void addSlotCavity(wxXmlNode *aContentNode, const PAD &aPad, const wxString &aName)
wxXmlNode * m_last_padstack
size_t lineHash(int aWidth, LINE_STYLE aDashType)
std::map< size_t, wxString > m_std_shape_dict
void addAttribute(wxXmlNode *aNode, const wxString &aName, const wxString &aValue)
wxXmlNode * m_shape_user_node
wxXmlNode * generateAvlSection()
Creates the Approved Vendor List section.
wxXmlNode * generateHistorySection()
Creates the history section.
void addXY(wxXmlNode *aNode, const VECTOR2I &aVec, const char *aXName=nullptr, const char *aYName=nullptr)
wxXmlNode * m_shape_std_node
void addPadStack(wxXmlNode *aContentNode, const PAD *aPad)
std::map< FOOTPRINT *, wxString > m_OEMRef_dict
void clearLoadedFootprints()
Frees the memory allocated for the loaded footprints in m_loaded_footprints.
std::map< std::pair< PCB_LAYER_ID, PCB_LAYER_ID >, std::vector< PAD * > > m_slot_holes
std::map< size_t, wxString > m_footprint_dict
wxXmlNode * generateLogisticSection()
Creates the logistical data header.
std::set< wxString > m_element_names
std::map< size_t, wxString > m_line_dict
void addLineDesc(wxXmlNode *aNode, int aWidth, LINE_STYLE aDashType, bool aForce=false)
void addKnockoutText(wxXmlNode *aContentNode, PCB_TEXT *aText)
std::map< size_t, wxString > m_padstack_dict
std::map< std::pair< PCB_LAYER_ID, PCB_LAYER_ID >, std::vector< BOARD_ITEM * > > m_drill_layers
std::map< wxString, FOOTPRINT * > m_footprint_refdes_dict
void generateProfile(wxXmlNode *aStepNode)
void generateLayerFeatures(wxXmlNode *aStepNode)
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
wxXmlNode * generateBOMSection(wxXmlNode *aEcadNode)
Creates the BOM section.
wxXmlNode * generateContentStackup(wxXmlNode *aContentNode)
void addShape(wxXmlNode *aContentNode, const PCB_SHAPE &aShape)
void generateAuxilliaryLayers(wxXmlNode *aCadLayerNode)
void addCadHeader(wxXmlNode *aEcadNode)
void generateLayerSetAuxilliary(wxXmlNode *aStepNode)
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
const std::map< std::string, UTF8 > * m_props
wxString genLayersString(PCB_LAYER_ID aTop, PCB_LAYER_ID aBottom, const char *aPrefix) const
void generateLogicalNets(wxXmlNode *aStepNode)
void addFillDesc(wxXmlNode *aNode, FILL_T aFillType, bool aForce=false)
std::map< size_t, wxString > m_user_shape_dict
size_t shapeHash(const PCB_SHAPE &aShape)
~PCB_IO_IPC2581() override
wxString genString(const wxString &aStr, const char *aPrefix=nullptr) const
std::vector< FOOTPRINT * > m_loaded_footprints
bool addPolygonCutouts(wxXmlNode *aParentNode, const SHAPE_POLY_SET::POLYGON &aPolygon)
std::set< wxUniChar > m_acceptable_chars
void addLayerAttributes(wxXmlNode *aNode, PCB_LAYER_ID aLayer)
wxXmlNode * generateXmlHeader()
Creates the XML header for IPC-2581.
wxXmlNode * generateEcadSection()
Creates the ECAD section.
wxXmlDocument * m_xml_doc
wxXmlNode * insertNode(wxXmlNode *aParent, const wxString &aName)
void addPad(wxXmlNode *aContentNode, const PAD *aPad, PCB_LAYER_ID aLayer)
void generateStepSection(wxXmlNode *aCadNode)
std::map< PCB_LAYER_ID, wxString > m_layer_name_map
std::map< wxString, wxString > m_generated_names
void addLocationNode(wxXmlNode *aContentNode, double aX, double aY)
std::map< int, std::vector< std::pair< wxString, wxString > > > m_net_pin_dict
std::map< FOOTPRINT *, wxString > m_footprint_refdes_reverse_dict
wxXmlNode * m_enterpriseNode
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
STROKE_PARAMS GetStroke() const override
VECTOR2I GetPosition() const override
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
virtual int GetWidth() const
PCB_LAYER_ID BottomLayer() const
VECTOR2I GetPosition() const override
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
const PADSTACK & Padstack() const
int GetWidth() const override
PCB_LAYER_ID TopLayer() const
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 Width() const
Get the current width of the segments in the chain.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
virtual void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const =0
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
LINE_STYLE GetLineStyle() const
Handle a list of polygons defining a copper zone.
void SetProgressCallback(std::function< void(size_t)> aCallback)
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
@ ROUND_ALL_CORNERS
All angles are rounded.
static bool empty(const wxTextEntryBase *aCtrl)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_180
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_SHAPE
Fill with object color.
static const wxChar traceIpc2581[]
This program source code file is part of KiCad, a free EDA CAD application.
static constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
static constexpr std::size_t hash_val(const Types &... args)
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.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
bool IsValidLayer(int aLayerId)
Test whether a given integer is a valid layer index, i.e.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ PTH
Plated through hole pad.
static bool isOppositeSideSilk(const FOOTPRINT *aFootprint, PCB_LAYER_ID aLayer)
std::vector< FAB_LAYER_COLOR > dummy
const std::vector< FAB_LAYER_COLOR > & GetStandardColors(BOARD_STACKUP_ITEM_TYPE aType)
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
LINE_STYLE
Dashed line types.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D