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" );
1147 int maxError =
m_board->GetDesignSettings().m_MaxError;
1158 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1166 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1168 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1171 return logisticNode;
1182 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1184 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1186 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1187 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1188 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1191 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1194 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1196 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1197 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1220 m_refdes =
new std::vector<REFDES>();
1221 m_props =
new std::map<wxString, wxString>();
1232 wxString m_OEMDesignRef;
1236 wxString m_description;
1238 std::vector<REFDES>* m_refdes;
1239 std::map<wxString, wxString>*
m_props;
1242 std::set<std::unique_ptr<struct BOM_ENTRY>,
1243 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1244 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1245 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1246 const std::unique_ptr<struct BOM_ENTRY>& b )
1248 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1253 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1254 fp->SetParentGroup(
nullptr );
1255 fp->SetPosition( {0, 0} );
1256 fp->SetOrientation(
ANGLE_0 );
1263 Report( wxString::Format(
_(
"Footprint %s not found in dictionary; BOM data may be incomplete." ),
1264 fp->GetFPID().GetLibItemName().wx_str() ),
1269 auto entry = std::make_unique<struct BOM_ENTRY>();
1275 entry->m_OEMDesignRef = it->second;
1279 Report( wxString::Format(
_(
"Component \"%s\" missing OEM reference; BOM entry will be skipped." ),
1280 fp->GetFPID().GetLibItemName().wx_str() ),
1284 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1286 entry->m_pads = fp->GetPadCount();
1291 entry->m_type =
"DOCUMENT";
1293 entry->m_type =
"ELECTRICAL";
1298 if( descField && !descField->
GetText().IsEmpty() )
1299 entry->m_description = descField->
GetText();
1301 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1304 ( *bom_iter )->m_count++;
1308 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1312 ( *bom_iter )->m_refdes->push_back( refdes );
1316 for(
PCB_FIELD* prop : fp->GetFields() )
1321 if( prop->IsMandatory() && !prop->IsValue() )
1324 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1328 if( bom_entries.empty() )
1331 wxFileName fn(
m_board->GetFileName() );
1333 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1334 m_xml_root->InsertChild( bomNode, aEcadNode );
1337 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1341 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1344 for(
const auto& entry : bom_entries )
1346 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1347 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1348 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1349 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1350 addAttribute( bomEntryNode,
"category", entry->m_type );
1352 if( !entry->m_description.IsEmpty() )
1353 addAttribute( bomEntryNode,
"description", entry->m_description );
1355 for(
const REFDES& refdes : *( entry->m_refdes ) )
1357 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1360 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1361 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1364 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1365 addAttribute( characteristicsNode,
"category", entry->m_type );
1367 for(
const auto& prop : *( entry->m_props ) )
1369 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1370 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1371 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1372 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1390 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1407 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1408 std::set<PCB_LAYER_ID> added_layers;
1410 for(
int i = 0; i < stackup.
GetCount(); i++ )
1414 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1418 if( ly_name.IsEmpty() )
1427 if( sublayer_id > 0 )
1428 ly_name += wxString::Format(
"_%d", sublayer_id );
1432 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1434 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1436 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1438 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1440 switch ( stackup_item->
GetType() )
1445 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1447 propertyNode =
appendNode( conductorNode,
"Property" );
1448 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1449 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1455 propertyNode =
appendNode( generalNode,
"Property" );
1456 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1458 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1459 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1460 propertyNode =
appendNode( dielectricNode,
"Property" );
1463 dielectricNode =
appendNode( specNode,
"Dielectric" );
1464 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1465 propertyNode =
appendNode( dielectricNode,
"Property" );
1472 propertyNode =
appendNode( generalNode,
"Property" );
1473 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1475 propertyNode =
appendNode( generalNode,
"Property" );
1476 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1481 propertyNode =
appendNode( generalNode,
"Property" );
1482 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1484 propertyNode =
appendNode( generalNode,
"Property" );
1485 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1498 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1540 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1581 aLayer ==
F_Cu ?
"TOP"
1582 : aLayer ==
B_Cu ?
"BOTTOM"
1597 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1598 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1605 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1607 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1608 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1613 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1614 std::set<PCB_LAYER_ID> added_layers;
1616 for(
int i = 0; i < stackup.
GetCount(); i++ )
1620 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1623 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1626 if( ly_name.IsEmpty() )
1635 if( sublayer_id > 0 )
1636 ly_name += wxString::Format(
"_%d", sublayer_id );
1640 ly_name =
genString( ly_name,
"LAYER" );
1642 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1646 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", i ) );
1648 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1649 addAttribute( specLayerNode,
"id", wxString::Format(
"SPEC_%s", ly_name ) );
1662 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1663 std::set<PCB_LAYER_ID> added_layers;
1665 for(
int i = 0; i < stackup.
GetCount(); i++ )
1672 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1674 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1677 if( ly_name.IsEmpty() )
1687 if( sublayer_id > 0 )
1688 ly_name += wxString::Format(
"_%d", sublayer_id );
1692 ly_name =
genString( ly_name,
"LAYER" );
1699 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1701 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1716 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
1725 added_layers.insert( layer );
1726 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1747 for(
PAD*
pad : fp->Pads() )
1749 if(
pad->HasDrilledHole() )
1751 else if(
pad->HasHole() )
1758 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1759 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
1764 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1771 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1772 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
1778 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1794 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
1796 if(
via->Padstack().IsFilled().value_or(
false ) )
1799 if(
via->Padstack().IsCapped().value_or(
false ) )
1804 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
1807 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
1810 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
1814 for(
auto& tuple : new_layers )
1820 bool add_node =
true;
1823 wxString layerFunction;
1826 switch( std::get<0>(layers) )
1830 layerFunction =
"COATINGNONCOND";
1834 layerFunction =
"HOLEFILL";
1838 layerFunction =
"COATINGNONCOND";
1842 layerFunction =
"HOLEFILL";
1846 layerFunction =
"COATINGCOND";
1854 if( add_node && !vec.empty() )
1856 wxXmlNode* node =
appendNode( aCadLayerNode,
"LAYER" );
1870 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
1871 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
1873 if( first_external )
1875 if( second_external )
1882 if( second_external )
1888 wxXmlNode* spanNode =
appendNode( node,
"SPAN" );
1899 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1900 wxFileName fn(
m_board->GetFileName() );
1906 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1926 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1933 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1940 addShape( padNode, *aPad, aLayer );
1944 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1957 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1978 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1985 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1999 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2000 padStackHoleNode->AddAttribute(
"name",
2001 wxString::Format(
"%s%d_%d",
2019 if( !
m_board->IsLayerEnabled( layer ) )
2022 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2024 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2032 addShape( padStackPadDefNode, shape );
2036 addShape( padStackPadDefNode, *aPad, layer );
2048 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2055 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2060 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2063 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2072 bool drill ) ->
void
2077 shape.
SetEnd( {
KiROUND( aVia->GetDrillValue() / 2.0 ), 0 } );
2079 shape.
SetEnd( {
KiROUND( aVia->GetWidth( layer ) / 2.0 ), 0 } );
2081 wxXmlNode* padStackPadDefNode =
2082 appendNode( padStackDefNode,
"PadstackPadDef" );
2084 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2087 addShape( padStackPadDefNode, shape );
2107 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2110 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2113 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2122 wxXmlNode* polygonNode =
nullptr;
2130 polygonNode =
appendNode( aParentNode,
"Polygon" );
2131 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2133 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2134 addXY( polybeginNode, pts[0] );
2136 for(
size_t ii = 1; ii < pts.size(); ++ii )
2138 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2139 addXY( polyNode, pts[ii] );
2142 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2143 addXY( polyendNode, pts[0] );
2154 addLineDesc( polygonNode, aWidth, aDashType,
true );
2158 wxCHECK( aWidth == 0,
false );
2171 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2173 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2175 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2176 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2178 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2179 addXY( polybeginNode, hole[0] );
2181 for(
size_t jj = 1; jj < hole.size(); ++jj )
2183 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2184 addXY( polyNode, hole[jj] );
2187 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2188 addXY( polyendNode, hole[0] );
2201 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2221 outline = &bbox_outline;
2226 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2228 if( !outlineNode->GetChildren() )
2230 aParentNode->RemoveChild( outlineNode );
2247 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2257 aParentNode->RemoveChild( contourNode );
2270 if( !
m_board->GetBoardPolygonOutlines( board_outline ) )
2276 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2280 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2281 aStepNode->RemoveChild( profileNode );
2304 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2305 fp->SetParentGroup(
nullptr );
2306 fp->SetPosition( { 0, 0 } );
2307 fp->SetOrientation(
ANGLE_0 );
2311 fp->GetFPID().GetLibItemName().wx_str(),
2315 addAttribute( aContentNode,
"packageRef", iter->second );
2322 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2323 wxXmlNode* otherSideViewNode =
nullptr;
2329 if( fp->FindPadByNumber(
"1" ) )
2331 else if ( fp->FindPadByNumber(
"A1" ) )
2333 else if ( fp->FindPadByNumber(
"A" ) )
2335 else if ( fp->FindPadByNumber(
"a" ) )
2337 else if ( fp->FindPadByNumber(
"a1" ) )
2339 else if ( fp->FindPadByNumber(
"Anode" ) )
2341 else if ( fp->FindPadByNumber(
"ANODE" ) )
2346 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2358 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2370 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2374 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2376 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2401 elements[item->GetLayer()][is_abs].push_back( item );
2404 auto add_base_node =
2407 wxXmlNode* parent = packageNode;
2412 if( !otherSideViewNode )
2413 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2415 parent = otherSideViewNode;
2421 name =
"SilkScreen";
2422 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2423 name =
"AssemblyDrawing";
2431 auto add_marking_node =
2432 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2434 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2436 return marking_node;
2439 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2440 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2444 if( elements.find( layer ) != elements.end() )
2446 if( elements[layer][
true].size() > 0 )
2447 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2448 else if( elements[layer][
false].size() > 0 )
2449 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2453 for(
auto& [layer, map] : elements )
2455 wxXmlNode* layer_node = add_base_node( layer );
2456 wxXmlNode* marking_node = add_marking_node( layer_node );
2457 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2458 bool update_bbox =
false;
2462 layer_nodes[layer] = layer_node;
2466 for(
auto& [is_abs, vec] : map )
2470 wxXmlNode* output_node =
nullptr;
2473 layer_bbox[layer].Merge( item->GetBoundingBox() );
2476 output_node = add_marking_node( layer_node );
2478 output_node = group_node;
2480 switch( item->Type() )
2486 if(
text->IsKnockout() )
2500 if(
text->IsBorderEnabled() )
2503 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2505 text->GetBorderWidth() );
2526 if( group_node->GetChildren() ==
nullptr )
2528 marking_node->RemoveChild( group_node );
2529 layer_node->RemoveChild( marking_node );
2531 delete marking_node;
2535 for(
auto&[layer, bbox] : layer_bbox )
2537 if( bbox.GetWidth() > 0 )
2539 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2542 std::vector<VECTOR2I> points( 4 );
2543 points[0] = bbox.GetPosition();
2544 points[2] = bbox.GetEnd();
2545 points[1].x = points[0].x;
2546 points[1].y = points[2].y;
2547 points[3].x = points[2].x;
2548 points[3].y = points[0].y;
2550 outline.
Append( points );
2556 std::map<wxString, wxXmlNode*> pin_nodes;
2558 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2560 PAD*
pad = fp->Pads()[ii];
2562 wxXmlNode* pinNode =
nullptr;
2564 auto [ it, inserted ] = pin_nodes.emplace(
name,
nullptr );
2569 it->second = pinNode;
2577 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2578 else if(
pad->IsOnCopperLayer() )
2579 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2581 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2583 if(
pad->HasHole() )
2588 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2590 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2591 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
2593 if( fp->IsFlipped() )
2602 pinNode = it->second;
2620 std::vector<wxXmlNode*> componentNodes;
2621 std::vector<wxXmlNode*> packageNodes;
2622 std::set<wxString> packageNames;
2624 bool generate_unique =
m_OEMRef.empty();
2628 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2630 wxXmlNode* pkg =
addPackage( componentNode, fp );
2633 packageNodes.push_back( pkg );
2639 if( !generate_unique )
2642 if( field && !field->
GetText().empty() )
2648 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2649 fp->GetFPID().GetLibItemName().wx_str(),
2654 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
2662 else if( fp->GetAttributes() &
FP_SMD )
2667 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
2669 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2673 if( fp->IsFlipped() )
2679 if( fp->IsFlipped() )
2683 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2685 componentNodes.push_back( componentNode );
2694 for( wxXmlNode* pkg : packageNodes )
2695 aStepNode->AddChild( pkg );
2697 for( wxXmlNode* cmp : componentNodes )
2698 aStepNode->AddChild( cmp );
2706 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2708 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
2710 for(
auto& [cmp,
pin] : pin_pair )
2712 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2726 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2730 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2732 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
2733 [&layers, &elements](
PCB_TRACK* aTrack )
2735 if( aTrack->Type() == PCB_VIA_T )
2737 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2739 for( PCB_LAYER_ID layer : layers )
2741 if( via->FlashLayer( layer ) )
2742 elements[layer][via->GetNetCode()].push_back( via );
2747 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2751 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2752 [ &elements ](
ZONE* zone )
2754 LSEQ zone_layers = zone->GetLayerSet().Seq();
2756 for( PCB_LAYER_ID layer : zone_layers )
2757 elements[layer][zone->GetNetCode()].push_back( zone );
2760 for(
BOARD_ITEM* item : m_board->Drawings() )
2763 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2765 elements[item->GetLayer()][0].push_back( item );
2768 for(
FOOTPRINT* fp : m_board->Footprints() )
2770 for(
PCB_FIELD* field : fp->GetFields() )
2771 elements[field->GetLayer()][0].push_back( field );
2773 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2774 elements[item->GetLayer()][0].push_back( item );
2776 for(
PAD*
pad : fp->Pads() )
2778 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2782 if(
pad->FlashLayer( layer ) )
2783 elements[layer][
pad->GetNetCode()].push_back(
pad );
2790 if( m_progressReporter )
2791 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2793 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2794 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2796 auto process_net = [&] (
int net )
2798 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
2803 std::stable_sort( vec.begin(), vec.end(),
2806 if( a->GetParentFootprint() == b->GetParentFootprint() )
2807 return a->Type() < b->Type();
2809 return a->GetParentFootprint() < b->GetParentFootprint();
2812 generateLayerSetNet( layerNode, layer, vec );
2817 if( m_progressReporter )
2819 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2820 m_board->GetLayerName( layer ),
2821 net->GetNetname() ) );
2822 m_progressReporter->AdvanceProgress();
2825 process_net( net->GetNetCode() );
2828 if( layerNode->GetChildren() ==
nullptr )
2830 aStepNode->RemoveChild( layerNode );
2843 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2844 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2855 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
2860 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2863 if(
via->GetNetCode() > 0 )
2866 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2867 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2872 addXY( holeNode,
via->GetPosition() );
2881 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
2886 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2889 if(
pad->GetNetCode() > 0 )
2892 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2893 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2899 addXY( holeNode,
pad->GetPosition() );
2908 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2909 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2913 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2915 if(
pad->GetNetCode() > 0 )
2918 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2925 std::vector<BOARD_ITEM*>& aItems )
2927 auto it = aItems.begin();
2928 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2929 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2930 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2932 bool has_via =
false;
2933 bool has_pad =
false;
2935 wxXmlNode* padSetNode =
nullptr;
2937 wxXmlNode* viaSetNode =
nullptr;
2939 wxXmlNode* teardropLayerSetNode =
nullptr;
2940 wxXmlNode* teardropFeatureSetNode =
nullptr;
2942 bool teardrop_warning =
false;
2947 if( item->GetNetCode() > 0 )
2957 shape.
SetStart( track->GetStart() );
2958 shape.
SetEnd( track->GetEnd() );
2959 shape.
SetWidth( track->GetWidth() );
2976 viaSetNode = layerSetNode;
2981 viaSetNode =
appendNode( layerSetNode,
"Set" );
2983 if( track->GetNetCode() > 0 )
2990 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2997 wxXmlNode* zoneFeatureNode = specialNode;
2999 if( zone->IsTeardropArea() )
3003 if( !teardropFeatureSetNode )
3005 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
3006 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
3008 if( zone->GetNetCode() > 0 )
3011 genString( zone->GetNetname(),
"NET" ) );
3014 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3016 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3019 zoneFeatureNode = teardropFeatureSetNode;
3021 else if( !teardrop_warning )
3023 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3025 teardrop_warning =
true;
3032 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3033 wxString refDes =
componentName( zone->GetParentFootprint() );
3035 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3037 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3041 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3043 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3054 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3057 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3059 bool link_to_component =
true;
3062 link_to_component =
false;
3064 if( link_to_component )
3067 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3074 wxXmlNode* xformNode =
appendNode( tempFeature,
"Xform" );
3084 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3086 if( shape->GetNetCode() > 0 )
3089 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3106 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3108 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3113 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3118 bool link_to_component = fp !=
nullptr;
3121 link_to_component =
false;
3123 if( link_to_component )
3126 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3127 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3129 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3131 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3137 addText( tempFeature, text_item,
text->GetFontMetrics() );
3155 padSetNode = layerSetNode;
3160 padSetNode =
appendNode( aLayerNode,
"Set" );
3162 if(
pad->GetNetCode() > 0 )
3177 switch( item->Type() )
3182 add_track(
static_cast<PCB_TRACK*
>( item ) );
3190 add_pad(
static_cast<PAD*
>( item ) );
3194 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3219 if( specialNode->GetChildren() ==
nullptr )
3221 featureSetNode->RemoveChild( specialNode );
3225 if( featureSetNode->GetChildren() ==
nullptr )
3227 layerSetNode->RemoveChild( featureSetNode );
3228 delete featureSetNode;
3231 if( layerSetNode->GetChildren() ==
nullptr )
3233 aLayerNode->RemoveChild( layerSetNode );
3234 delete layerSetNode;
3245 bool add_node =
true;
3251 switch( std::get<0>(layers) )
3280 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3284 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3298 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3300 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3319 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3323 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3326 std::set<wxString> unique_parts;
3327 std::map<wxString,wxString> unique_vendors;
3331 auto [ it, success ] = unique_parts.insert(
name );
3336 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3343 for (
int ii = 0; ii < 2; ++ii )
3349 if( mpn_name.empty() )
3352 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3356 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3359 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3361 wxString
name = wxT(
"UNKNOWN" );
3364 if( !ii && company[ii] )
3372 else if( !ii && !company_name[ii].
empty() )
3374 name = company_name[ii];
3376 else if( ii && !
m_dist.empty() )
3381 auto [vendor_id, inserted] = unique_vendors.emplace(
3383 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3385 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3389 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3405 const std::map<std::string, UTF8>* aProperties )
3412 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3414 if( it->second ==
"inch" )
3421 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3422 m_sigfig = std::stoi( it->second );
3424 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3427 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3430 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3431 m_mpn = it->second.wx_str();
3433 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3434 m_mfg = it->second.wx_str();
3436 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3437 m_dist = it->second.wx_str();
3439 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3444 for(
char c =
'a'; c <=
'z'; ++c )
3447 for(
char c =
'A'; c <=
'Z'; ++c )
3450 for(
char c =
'0'; c <=
'9'; ++c )
3454 std::string specialChars =
"_\\-.+><";
3456 for(
char c : specialChars )
3485 double written_bytes = 0.0;
3486 double last_yield = 0.0;
3493 auto update_progress = [&](
size_t aBytes )
3495 written_bytes += aBytes;
3496 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
3501 if( last_yield + 0.01 < percent )
3503 last_yield = percent;
3517 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.
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
bool TransformHoleToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Build the corner list of the polygonal drill shape in the board coordinate system.
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.
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.
@ DESCRIPTION
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
@ 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