48#include <wx/numformatter.h>
49#include <wx/xml/xml.h>
127 std::vector<FOOTPRINT*> retval;
130 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
140 if( aParent->GetChildren() )
141 aNode->SetNext( aParent->GetChildren() );
143 aNode->SetNext(
nullptr );
145 aParent->SetChildren( aNode );
146 aNode->SetParent( aParent );
155 aNode->SetNext( aPrev->GetNext() );
156 aPrev->SetNext( aNode );
157 aNode->SetParent( aPrev->GetParent() );
178 check = check->GetParent();
191 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
206 aNode->SetParent( aParent );
211 aParent->AddChild( aNode );
223 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
237 str.Replace( wxT(
":" ), wxT(
"_" ) );
241 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
258 wxString key = aPrefix ? wxString( aPrefix ) + wxT(
":" ) + aStr : aStr;
268 wxString
name = base;
272 name = wxString::Format(
"%s_%d", base, suffix++ );
288 const char* aPrefix )
const
290 return genString( wxString::Format( wxS(
"%s_%s" ),
292 m_board->GetLayerName( aBottom ) ), aPrefix );
303 if(
name.empty() && fp )
307 if( fp->
Pads()[ii] == aPad )
315 name = wxString::Format(
"NPTH%zu", ii );
316 else if(
name.empty() )
317 name = wxString::Format(
"PAD%zu", ii );
328 [&](
const wxString& aName )
347 wxString
name = baseName;
350 while( !tryInsert(
name ) )
351 name = wxString::Format(
"%s_%d", baseName, suffix++ );
361 wxString str = wxString::FromCDouble( aVal, aSigFig == -1 ?
m_sigfig : aSigFig );
364 while( str.EndsWith( wxT(
"00" ) ) )
368 if( str == wxT(
"-0.0" ) )
393 aNode->AddAttribute( aName, aValue );
399 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
401 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
402 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
403 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
408 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
413 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
418 return xmlHeaderNode;
430 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
438 wxFileName fn(
m_board->GetFileName() );
445 contentNode->AddChild( color_node );
449 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
469 contentNode->AddChild( color_node );
478 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
553 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
557 wxString layer_name = item->GetLayerName();
558 int sub_layer_count = 1;
560 if( layer_name.empty() )
561 layer_name =
m_board->GetLayerName( item->GetBrdLayerId() );
563 layer_name =
genString( layer_name,
"LAYER" );
567 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
569 sub_layer_count = item->GetSublayersCount();
576 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
578 wxString sub_layer_name = layer_name;
581 sub_layer_name += wxString::Format(
"_%d", sub_idx );
583 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
589 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
591 wxXmlNode* color =
appendNode( entry_color,
"Color" );
593 wxString colorName = item->GetColor( sub_idx );
595 if( colorName.StartsWith( wxT(
"#" ) ) )
598 COLOR4D layer_color( colorName );
610 if( fab_color.GetName() == colorName )
612 addAttribute( color,
"r", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).r * 255 ) ) );
613 addAttribute( color,
"g", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).g * 255 ) ) );
614 addAttribute( color,
"b", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).b * 255 ) ) );
634 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
640 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
641 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
648 wxCHECK_RET( aNode,
"aNode is null" );
653 wxXmlNode* entry_node =
nullptr;
657 size_t hash =
lineHash( aWidth, aDashType );
658 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
662 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
677 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
724 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
726 std::list<VECTOR2I> pts;
734 wxXmlNode* line_node =
nullptr;
741 addXY( line_node, pts.front(),
"startX",
"startY" );
742 addXY( line_node, pts.back(),
"endX",
"endY" );
746 line_node =
appendNode( text_node,
"Polyline" );
747 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
748 addXY( point_node, pts.front() );
750 auto iter = pts.begin();
752 for( ++iter; iter != pts.end(); ++iter )
754 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
755 addXY( point_node, *iter );
770 if( aPt1 == pts.back() )
771 pts.push_back( aPt2 );
772 else if( aPt2 == pts.front() )
773 pts.push_front( aPt1 );
774 else if( aPt1 == pts.front() )
775 pts.push_front( aPt2 );
776 else if( aPt2 == pts.back() )
777 pts.push_back( aPt1 );
781 pts.push_back( aPt1 );
782 pts.push_back( aPt2 );
787 pts.push_back( aPt1 );
788 pts.push_back( aPt2 );
794 if( aPoly.PointCount() < 3 )
797 wxXmlNode* outline_node =
appendNode( text_node,
"Outline" );
798 wxXmlNode* poly_node =
appendNode( outline_node,
"Polygon" );
801 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
802 wxXmlNode* point_node =
appendNode( poly_node,
"PolyBegin" );
803 addXY( point_node, pts.front() );
805 for(
size_t ii = 1; ii < pts.size(); ++ii )
807 wxXmlNode* point_node =
809 addXY( point_node, pts[ii] );
812 point_node =
appendNode( poly_node,
"PolyStepSegment" );
813 addXY( point_node, pts.front() );
824 if( text_node->GetChildren() ==
nullptr )
826 aContentNode->RemoveChild( text_node );
839 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
844 int maxError =
m_board->GetDesignSettings().m_MaxError;
864 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
865 circle_node->AddAttribute(
"diameter",
878 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
894 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
910 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
914 roundrect_node->AddAttribute(
"radius",
932 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
937 int shorterSide = std::min( pad_size.
x, pad_size.
y );
968 int dx = pad_size.
x / 2;
969 int dy = pad_size.
y / 2;
970 int ddx = trap_delta.
x / 2;
971 int ddy = trap_delta.
y / 2;
973 outline.
Append( -dx - ddy, dy + ddx );
974 outline.
Append( dx + ddy, dy - ddx );
975 outline.
Append( dx - ddy, -dy + ddx );
976 outline.
Append( -dx + ddy, -dy - ddx );
1001 if( expansion !=
VECTOR2I( 0, 0 ) )
1018 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
1033 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1050 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1058 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1059 addXY( begin_node, start );
1062 wxXmlNode* arc1_node =
appendNode( polyline_node,
"PolyStepCurve" );
1063 addXY( arc1_node, mid );
1068 wxXmlNode* arc2_node =
appendNode( polyline_node,
"PolyStepCurve" );
1069 addXY( arc2_node, start );
1081 int diameter = aShape.
GetRadius() * 2.0;
1088 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1090 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
1116 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1121 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1122 addXY( begin_node, corners[0] );
1124 for(
size_t i = 1; i < corners.size(); ++i )
1126 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1127 addXY( step_node, corners[i] );
1131 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1132 addXY( close_node, corners[0] );
1134 if( stroke_width > 0 )
1135 addLineDesc( polyline_node, stroke_width, dash,
true );
1145 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1152 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1169 width += stroke_width;
1170 height += stroke_width;
1198 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1199 const std::vector<VECTOR2I>& pts = outline.
CPoints();
1201 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1202 addXY( begin_node, pts[0] );
1204 for(
size_t jj = 1; jj < pts.size(); ++jj )
1206 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1207 addXY( step_node, pts[jj] );
1211 if( pts.size() > 2 && pts.front() != pts.back() )
1213 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1214 addXY( close_node, pts[0] );
1217 if( stroke_width > 0 )
1218 addLineDesc( polyline_node, stroke_width, dash,
true );
1232 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1254 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1256 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1273 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1277 std::vector<VECTOR2I> points;
1280 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1281 addXY( point_node, points[0] );
1283 for(
size_t i = 1; i < points.size(); i++ )
1285 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1286 addXY( point_node, points[i] );
1300 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1302 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1318 if( !aInline && !
name.empty() )
1320 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1329 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1349 if( drill_size.
y > drill_size.
x )
1351 std::swap( drill_size.
x, drill_size.
y );
1358 wxXmlNode* xformNode =
appendNode( slotNode,
"Xform" );
1363 wxXmlNode* ovalNode =
appendNode( slotNode,
"Oval" );
1371 int maxError =
m_board->GetDesignSettings().m_MaxError;
1383 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1391 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1393 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1396 return logisticNode;
1407 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1409 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1411 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1412 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1413 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1416 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1419 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1421 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1422 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1445 m_refdes =
new std::vector<REFDES>();
1446 m_props =
new std::map<wxString, wxString>();
1457 wxString m_OEMDesignRef;
1461 wxString m_description;
1463 std::vector<REFDES>* m_refdes;
1464 std::map<wxString, wxString>*
m_props;
1467 std::set<std::unique_ptr<struct BOM_ENTRY>,
1468 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1469 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1470 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1471 const std::unique_ptr<struct BOM_ENTRY>& b )
1473 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1478 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1479 fp->SetParentGroup(
nullptr );
1480 fp->SetPosition( {0, 0} );
1481 fp->SetOrientation(
ANGLE_0 );
1484 if( fp->IsFlipped() )
1492 Report( wxString::Format(
_(
"Footprint %s not found in dictionary; BOM data may be incomplete." ),
1493 fp->GetFPID().GetLibItemName().wx_str() ),
1498 auto entry = std::make_unique<struct BOM_ENTRY>();
1504 entry->m_OEMDesignRef = it->second;
1508 Report( wxString::Format(
_(
"Component \"%s\" missing OEM reference; BOM entry will be skipped." ),
1509 fp->GetFPID().GetLibItemName().wx_str() ),
1513 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1515 entry->m_pads = fp->GetPadCount();
1519 const wxString variantName =
m_board ?
m_board->GetCurrentVariant() : wxString();
1521 if( entry->m_pads == 0 || fp_it->GetExcludedFromBOMForVariant( variantName ) )
1522 entry->m_type =
"DOCUMENT";
1524 entry->m_type =
"ELECTRICAL";
1529 if( descField && !descField->
GetShownText(
false ).IsEmpty() )
1530 entry->m_description = descField->
GetShownText(
false );
1532 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1535 ( *bom_iter )->m_count++;
1539 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1540 refdes.m_populate = !fp->GetDNPForVariant( variantName )
1541 && !fp->GetExcludedFromBOMForVariant( variantName );
1544 ( *bom_iter )->m_refdes->push_back( refdes );
1548 for(
PCB_FIELD* prop : fp->GetFields() )
1553 if( prop->IsMandatory() && !prop->IsValue() )
1556 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetShownText(
false ) );
1560 if( bom_entries.empty() )
1563 wxFileName fn(
m_board->GetFileName() );
1565 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1566 m_xml_root->InsertChild( bomNode, aEcadNode );
1569 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1573 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1576 for(
const auto& entry : bom_entries )
1578 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1579 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1580 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1581 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1582 addAttribute( bomEntryNode,
"category", entry->m_type );
1584 if( !entry->m_description.IsEmpty() )
1585 addAttribute( bomEntryNode,
"description", entry->m_description );
1587 for(
const REFDES& refdes : *( entry->m_refdes ) )
1589 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1592 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1593 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1596 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1597 addAttribute( characteristicsNode,
"category", entry->m_type );
1599 for(
const auto& prop : *( entry->m_props ) )
1601 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1602 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1603 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1604 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1622 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1641 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1642 std::set<PCB_LAYER_ID> added_layers;
1644 for(
int i = 0; i < stackup.
GetCount(); i++ )
1648 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1652 if( ly_name.IsEmpty() )
1661 if( sublayer_id > 0 )
1662 ly_name += wxString::Format(
"_%d", sublayer_id );
1666 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1668 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1670 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1672 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1674 switch ( stackup_item->
GetType() )
1679 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1681 propertyNode =
appendNode( conductorNode,
"Property" );
1682 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1683 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1689 propertyNode =
appendNode( generalNode,
"Property" );
1690 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1692 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1693 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1694 propertyNode =
appendNode( dielectricNode,
"Property" );
1697 dielectricNode =
appendNode( specNode,
"Dielectric" );
1698 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1699 propertyNode =
appendNode( dielectricNode,
"Property" );
1706 propertyNode =
appendNode( generalNode,
"Property" );
1707 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1709 propertyNode =
appendNode( generalNode,
"Property" );
1710 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1716 propertyNode =
appendNode( generalNode,
"Property" );
1717 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1719 propertyNode =
appendNode( generalNode,
"Property" );
1720 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1724 if( stackup_item->
GetEpsilonR( sublayer_id ) > 1.0 )
1726 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1727 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1728 propertyNode =
appendNode( dielectricNode,
"Property" );
1735 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1736 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1737 propertyNode =
appendNode( dielectricNode,
"Property" );
1753 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1756 wxXmlNode* surfaceFinishNode =
appendNode( specNode,
"SurfaceFinish" );
1757 wxXmlNode* finishNode =
appendNode( surfaceFinishNode,
"Finish" );
1769 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1813 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1854 aLayer ==
F_Cu ?
"TOP"
1855 : aLayer ==
B_Cu ?
"BOTTOM"
1873 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1874 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1881 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1883 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1884 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1889 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1890 std::set<PCB_LAYER_ID> added_layers;
1893 for(
int i = 0; i < stackup.
GetCount(); i++ )
1897 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1902 if( hasCoating && layer_id ==
F_Cu && sublayer_id == 0 )
1904 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1905 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_TOP" );
1909 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1911 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1915 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1918 if( ly_name.IsEmpty() )
1927 if( sublayer_id > 0 )
1928 ly_name += wxString::Format(
"_%d", sublayer_id );
1932 wxString spec_name =
genString( ly_name,
"SPEC_LAYER" );
1933 ly_name =
genString( ly_name,
"LAYER" );
1935 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1939 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1941 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1947 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1948 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_BOTTOM" );
1952 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1954 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1969 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1970 std::set<PCB_LAYER_ID> added_layers;
1972 for(
int i = 0; i < stackup.
GetCount(); i++ )
1979 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1981 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1984 if( ly_name.IsEmpty() )
1994 if( sublayer_id > 0 )
1995 ly_name += wxString::Format(
"_%d", sublayer_id );
1999 ly_name =
genString( ly_name,
"LAYER" );
2006 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
2008 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
2023 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
2032 added_layers.insert( layer );
2033 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2044 wxXmlNode* topCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2046 addAttribute( topCoatingNode,
"layerFunction",
"COATINGCOND" );
2048 addAttribute( topCoatingNode,
"polarity",
"POSITIVE" );
2050 wxXmlNode* botCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2051 addAttribute( botCoatingNode,
"name",
"COATING_BOTTOM" );
2052 addAttribute( botCoatingNode,
"layerFunction",
"COATINGCOND" );
2054 addAttribute( botCoatingNode,
"polarity",
"POSITIVE" );
2072 for(
PAD*
pad : fp->Pads() )
2074 if(
pad->HasDrilledHole() )
2076 else if(
pad->HasHole() )
2083 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2084 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2089 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2096 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2097 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2103 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2119 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
2121 if(
via->Padstack().IsFilled().value_or(
false ) )
2124 if(
via->Padstack().IsCapped().value_or(
false ) )
2129 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
2132 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
2135 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
2139 for(
auto& tuple : new_layers )
2145 bool add_node =
true;
2148 wxString layerFunction;
2151 switch( std::get<0>(layers) )
2155 layerFunction =
"COATINGNONCOND";
2159 layerFunction =
"HOLEFILL";
2163 layerFunction =
"COATINGNONCOND";
2167 layerFunction =
"HOLEFILL";
2171 layerFunction =
"COATINGCOND";
2179 if( add_node && !vec.empty() )
2181 wxXmlNode* node =
appendNode( aCadLayerNode,
"LAYER" );
2195 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
2196 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
2198 if( first_external )
2200 if( second_external )
2207 if( second_external )
2213 wxXmlNode* spanNode =
appendNode( node,
"SPAN" );
2224 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
2225 wxFileName fn(
m_board->GetFileName() );
2231 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
2251 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2258 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
2265 addShape( padNode, *aPad, aLayer );
2269 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
2282 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2303 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
2310 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2325 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2326 padStackHoleNode->AddAttribute(
"name",
2327 wxString::Format(
"%s%d_%d",
2345 if( !
m_board->IsLayerEnabled( layer ) )
2348 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2350 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2358 addShape( padStackPadDefNode, shape );
2362 addShape( padStackPadDefNode, *aPad, layer );
2374 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2381 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2387 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2390 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2399 bool drill ) ->
void
2404 shape.
SetEnd( {
KiROUND( aVia->GetDrillValue() / 2.0 ), 0 } );
2406 shape.
SetEnd( {
KiROUND( aVia->GetWidth( layer ) / 2.0 ), 0 } );
2408 wxXmlNode* padStackPadDefNode =
2409 appendNode( padStackDefNode,
"PadstackPadDef" );
2411 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2414 addShape( padStackPadDefNode, shape );
2434 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2437 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2440 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2455 if( secondary.
size.
x <= 0 && secondary.
size.
y <= 0 )
2466 if( !layerHasRef( secondary.
start ) || !layerHasRef( secondary.
end ) )
2487 wxXmlNode* backdrillNode =
appendNode( specNode,
"Backdrill" );
2488 addAttribute( backdrillNode,
"startLayerRef", startLayer->second );
2489 addAttribute( backdrillNode,
"mustNotCutLayerRef", endLayer->second );
2493 if( stubLength < 0 )
2508 addAttribute( backdrillNode,
"postMachining", isPostMachined ? wxT(
"true" )
2519 wxString primarySpec = createSpec( primary, wxString::Format( wxT(
"BD_%dA" ), specIndex ) );
2521 wxString secondarySpec = createSpec( secondary, wxString::Format( wxT(
"BD_%dB" ), specIndex ) );
2523 if( primarySpec.IsEmpty() && secondarySpec.IsEmpty() )
2538 auto addRef = [&](
const wxString& aSpecName )
2540 if( aSpecName.IsEmpty() )
2543 wxXmlNode* specRefNode =
appendNode( aHoleNode,
"SpecRef" );
2548 addRef( it->second.first );
2549 addRef( it->second.second );
2564 wxXmlNode* specNode = it->second;
2586 wxXmlNode* polygonNode =
nullptr;
2594 polygonNode =
appendNode( aParentNode,
"Polygon" );
2595 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2597 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2598 addXY( polybeginNode, pts[0] );
2600 for(
size_t ii = 1; ii < pts.size(); ++ii )
2602 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2603 addXY( polyNode, pts[ii] );
2606 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2607 addXY( polyendNode, pts[0] );
2618 addLineDesc( polygonNode, aWidth, aDashType,
true );
2622 wxCHECK( aWidth == 0,
false );
2635 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2637 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2639 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2640 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2642 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2643 addXY( polybeginNode, hole[0] );
2645 for(
size_t jj = 1; jj < hole.size(); ++jj )
2647 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2648 addXY( polyNode, hole[jj] );
2651 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2652 addXY( polyendNode, hole[0] );
2665 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2685 outline = &bbox_outline;
2690 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2692 if( !outlineNode->GetChildren() )
2694 aParentNode->RemoveChild( outlineNode );
2711 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2721 aParentNode->RemoveChild( contourNode );
2734 if( !
m_board->GetBoardPolygonOutlines( board_outline,
false ) )
2740 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2744 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2745 aStepNode->RemoveChild( profileNode );
2768 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2769 fp->SetParentGroup(
nullptr );
2770 fp->SetPosition( { 0, 0 } );
2771 fp->SetOrientation(
ANGLE_0 );
2776 bool wasFlipped = fp->IsFlipped();
2779 if( fp->IsFlipped() )
2784 fp->GetFPID().GetLibItemName().wx_str(),
2788 addAttribute( aContentNode,
"packageRef", iter->second );
2795 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2796 wxXmlNode* otherSideViewNode =
nullptr;
2802 if( fp->FindPadByNumber(
"1" ) )
2804 else if ( fp->FindPadByNumber(
"A1" ) )
2806 else if ( fp->FindPadByNumber(
"A" ) )
2808 else if ( fp->FindPadByNumber(
"a" ) )
2810 else if ( fp->FindPadByNumber(
"a1" ) )
2812 else if ( fp->FindPadByNumber(
"Anode" ) )
2814 else if ( fp->FindPadByNumber(
"ANODE" ) )
2819 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2824 : fp->GetCourtyard(
F_CrtYd );
2826 : fp->GetCourtyard(
B_CrtYd );
2836 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2848 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2852 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2854 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2879 elements[item->GetLayer()][is_abs].push_back( item );
2882 auto add_base_node =
2885 wxXmlNode* parent = packageNode;
2894 bool is_other_side = wasFlipped ? ( aLayer ==
F_SilkS || aLayer ==
F_Fab )
2899 if( !otherSideViewNode )
2900 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2902 parent = otherSideViewNode;
2908 name =
"SilkScreen";
2909 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2910 name =
"AssemblyDrawing";
2918 auto add_marking_node =
2919 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2921 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2923 return marking_node;
2926 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2927 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2931 if( elements.find( layer ) != elements.end() )
2933 if( elements[layer][
true].size() > 0 )
2934 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2935 else if( elements[layer][
false].size() > 0 )
2936 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2940 for(
auto& [layer, map] : elements )
2942 wxXmlNode* layer_node = add_base_node( layer );
2943 wxXmlNode* marking_node = add_marking_node( layer_node );
2944 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2945 bool update_bbox =
false;
2949 layer_nodes[layer] = layer_node;
2953 for(
auto& [is_abs, vec] : map )
2957 wxXmlNode* output_node =
nullptr;
2960 layer_bbox[layer].Merge( item->GetBoundingBox() );
2963 output_node = add_marking_node( layer_node );
2965 output_node = group_node;
2967 switch( item->Type() )
2973 if(
text->IsKnockout() )
2987 if(
text->IsBorderEnabled() )
2990 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2992 text->GetBorderWidth() );
3015 if( group_node->GetChildren() ==
nullptr )
3017 marking_node->RemoveChild( group_node );
3018 layer_node->RemoveChild( marking_node );
3020 delete marking_node;
3024 for(
auto&[layer, bbox] : layer_bbox )
3026 if( bbox.GetWidth() > 0 )
3028 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
3031 std::vector<VECTOR2I> points( 4 );
3032 points[0] = bbox.GetPosition();
3033 points[2] = bbox.GetEnd();
3034 points[1].x = points[0].x;
3035 points[1].y = points[2].y;
3036 points[3].x = points[2].x;
3037 points[3].y = points[0].y;
3039 outline.
Append( points );
3045 std::map<wxString, wxXmlNode*> pin_nodes;
3047 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
3049 PAD*
pad = fp->Pads()[ii];
3051 wxXmlNode* pinNode =
nullptr;
3053 auto [ it, inserted ] = pin_nodes.emplace(
name,
nullptr );
3058 it->second = pinNode;
3066 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
3067 else if(
pad->IsOnCopperLayer() )
3068 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
3070 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
3072 if(
pad->HasHole() )
3077 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
3079 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
3080 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
3082 if( fp->IsFlipped() )
3105 std::vector<wxXmlNode*> componentNodes;
3106 std::vector<wxXmlNode*> packageNodes;
3107 std::set<wxString> packageNames;
3109 bool generate_unique =
m_OEMRef.empty();
3113 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
3115 wxXmlNode* pkg =
addPackage( componentNode, fp );
3118 packageNodes.push_back( pkg );
3124 if( !generate_unique )
3127 if( field && !field->
GetText().empty() )
3133 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
3134 fp->GetFPID().GetLibItemName().wx_str(),
3139 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
3147 else if( fp->GetAttributes() &
FP_SMD )
3152 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
3154 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
3158 if( fp->IsFlipped() )
3164 if( fp->IsFlipped() )
3168 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
3170 componentNodes.push_back( componentNode );
3179 for( wxXmlNode* pkg : packageNodes )
3180 aStepNode->AddChild( pkg );
3182 for( wxXmlNode* cmp : componentNodes )
3183 aStepNode->AddChild( cmp );
3191 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
3193 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
3195 for(
auto& [cmp,
pin] : pin_pair )
3197 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
3211 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
3215 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
3217 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
3218 [&layers, &elements](
PCB_TRACK* aTrack )
3220 if( aTrack->Type() == PCB_VIA_T )
3222 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
3224 for( PCB_LAYER_ID layer : layers )
3226 if( via->FlashLayer( layer ) )
3227 elements[layer][via->GetNetCode()].push_back( via );
3232 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
3236 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
3237 [ &elements ](
ZONE* zone )
3239 LSEQ zone_layers = zone->GetLayerSet().Seq();
3241 for( PCB_LAYER_ID layer : zone_layers )
3242 elements[layer][zone->GetNetCode()].push_back( zone );
3245 for(
BOARD_ITEM* item : m_board->Drawings() )
3248 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
3250 elements[item->GetLayer()][0].push_back( item );
3253 for(
FOOTPRINT* fp : m_board->Footprints() )
3255 for(
PCB_FIELD* field : fp->GetFields() )
3256 elements[field->GetLayer()][0].push_back( field );
3258 for(
BOARD_ITEM* item : fp->GraphicalItems() )
3259 elements[item->GetLayer()][0].push_back( item );
3261 for(
PAD*
pad : fp->Pads() )
3263 LSEQ pad_layers =
pad->GetLayerSet().Seq();
3267 if(
pad->FlashLayer( layer ) )
3268 elements[layer][
pad->GetNetCode()].push_back(
pad );
3295 if( m_progressReporter )
3296 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
3298 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
3299 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
3301 auto process_net = [&] (
int net )
3303 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
3308 std::stable_sort( vec.begin(), vec.end(),
3311 if( a->GetParentFootprint() == b->GetParentFootprint() )
3312 return a->Type() < b->Type();
3314 return a->GetParentFootprint() < b->GetParentFootprint();
3317 generateLayerSetNet( layerNode, layer, vec );
3322 if( m_progressReporter )
3324 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
3325 m_board->GetLayerName( layer ),
3326 net->GetNetname() ) );
3327 m_progressReporter->AdvanceProgress();
3330 process_net( net->GetNetCode() );
3333 if( layerNode->GetChildren() ==
nullptr )
3335 aStepNode->RemoveChild( layerNode );
3336 deleteNode( layerNode );
3348 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3349 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
3360 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
3365 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3368 if(
via->GetNetCode() > 0 )
3371 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3372 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3377 addXY( holeNode,
via->GetPosition() );
3387 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
3392 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3395 if(
pad->GetNetCode() > 0 )
3398 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3399 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3405 addXY( holeNode,
pad->GetPosition() );
3415 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3416 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
3420 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3422 if(
pad->GetNetCode() > 0 )
3425 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
3432 std::vector<BOARD_ITEM*>& aItems )
3434 auto it = aItems.begin();
3435 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
3436 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
3437 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
3439 bool has_via =
false;
3440 bool has_pad =
false;
3442 wxXmlNode* padSetNode =
nullptr;
3444 wxXmlNode* viaSetNode =
nullptr;
3446 wxXmlNode* teardropLayerSetNode =
nullptr;
3447 wxXmlNode* teardropFeatureSetNode =
nullptr;
3449 bool teardrop_warning =
false;
3454 if( item->GetNetCode() > 0 )
3464 shape.
SetStart( track->GetStart() );
3465 shape.
SetEnd( track->GetEnd() );
3466 shape.
SetWidth( track->GetWidth() );
3483 viaSetNode = layerSetNode;
3488 viaSetNode =
appendNode( layerSetNode,
"Set" );
3490 if( track->GetNetCode() > 0 )
3497 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
3504 wxXmlNode* zoneFeatureNode = specialNode;
3506 if( zone->IsTeardropArea() )
3510 if( !teardropFeatureSetNode )
3512 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
3513 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
3515 if( zone->GetNetCode() > 0 )
3518 genString( zone->GetNetname(),
"NET" ) );
3521 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3523 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3526 zoneFeatureNode = teardropFeatureSetNode;
3528 else if( !teardrop_warning )
3530 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3532 teardrop_warning =
true;
3539 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3540 wxString refDes =
componentName( zone->GetParentFootprint() );
3542 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3544 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3548 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3550 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3561 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3564 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3566 bool link_to_component =
true;
3569 link_to_component =
false;
3571 if( link_to_component )
3574 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3581 wxXmlNode* xformNode =
appendNode( tempFeature,
"Xform" );
3592 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3594 if( shape->GetNetCode() > 0 )
3597 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3614 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3616 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3621 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3626 bool link_to_component = fp !=
nullptr;
3629 link_to_component =
false;
3631 if( link_to_component )
3634 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3635 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3637 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3639 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3645 addText( tempFeature, text_item,
text->GetFontMetrics() );
3663 padSetNode = layerSetNode;
3668 padSetNode =
appendNode( aLayerNode,
"Set" );
3670 if(
pad->GetNetCode() > 0 )
3685 switch( item->Type() )
3690 add_track(
static_cast<PCB_TRACK*
>( item ) );
3698 add_pad(
static_cast<PAD*
>( item ) );
3702 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3727 if( specialNode->GetChildren() ==
nullptr )
3729 featureSetNode->RemoveChild( specialNode );
3733 if( featureSetNode->GetChildren() ==
nullptr )
3735 layerSetNode->RemoveChild( featureSetNode );
3739 if( layerSetNode->GetChildren() ==
nullptr )
3741 aLayerNode->RemoveChild( layerSetNode );
3753 bool add_node =
true;
3759 switch( std::get<0>(layers) )
3788 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3792 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3806 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3808 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3832 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3836 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3839 std::set<wxString> unique_parts;
3840 std::map<wxString,wxString> unique_vendors;
3844 auto [ it, success ] = unique_parts.insert(
name );
3849 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3856 for (
int ii = 0; ii < 2; ++ii )
3862 if( mpn_name.empty() )
3865 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3869 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3872 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3874 wxString
name = wxT(
"UNKNOWN" );
3877 if( !ii && company[ii] )
3885 else if( !ii && !company_name[ii].
empty() )
3887 name = company_name[ii];
3889 else if( ii && !
m_dist.empty() )
3894 auto [vendor_id, inserted] = unique_vendors.emplace(
3896 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3898 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3902 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3918 const std::map<std::string, UTF8>* aProperties )
3961 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3963 if( it->second ==
"inch" )
3970 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3971 m_sigfig = std::stoi( it->second );
3973 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3976 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3979 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3980 m_mpn = it->second.wx_str();
3982 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3983 m_mfg = it->second.wx_str();
3985 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3986 m_dist = it->second.wx_str();
3988 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3993 for(
char c =
'a'; c <=
'z'; ++c )
3996 for(
char c =
'A'; c <=
'Z'; ++c )
3999 for(
char c =
'0'; c <=
'9'; ++c )
4003 std::string specialChars =
"_\\-.+><";
4005 for(
char c : specialChars )
4034 double written_bytes = 0.0;
4035 double last_yield = 0.0;
4042 auto update_progress = [&](
size_t aBytes )
4044 written_bytes += aBytes;
4045 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
4050 if( last_yield + 0.01 < percent )
4052 last_yield = percent;
4066 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
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
wxString m_FinishType
The name of external copper finish.
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.
std::vector< VECTOR2I > GetRectCorners() const
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, std::optional< VECTOR2I > aMousePos=std::nullopt, wxString *aActiveUrl=nullptr) 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.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
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.
POST_MACHINING_PROPS & FrontPostMachining()
std::optional< bool > IsPlugged(PCB_LAYER_ID aSide) const
std::optional< bool > IsCapped() const
std::optional< bool > IsCovered(PCB_LAYER_ID aSide) const
DRILL_PROPS & SecondaryDrill()
POST_MACHINING_PROPS & BackPostMachining()
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 PADSTACK & Padstack() const
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
PAD_DRILL_SHAPE GetDrillShape() const
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
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
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 addBackdrillSpecRefs(wxXmlNode *aHoleNode, const wxString &aPadstackName)
void generateDrillLayers(wxXmlNode *aCadLayerNode)
wxString sanitizeId(const wxString &aStr) const
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)
void addShape(wxXmlNode *aContentNode, const PCB_SHAPE &aShape, bool aInline=false)
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)
void deleteNode(wxXmlNode *&aNode)
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< wxString, wxXmlNode * > m_backdrill_spec_nodes
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...
std::map< wxString, std::pair< wxString, wxString > > m_padstack_backdrill_specs
wxXmlNode * generateBOMSection(wxXmlNode *aEcadNode)
Creates the BOM section.
wxXmlNode * generateContentStackup(wxXmlNode *aContentNode)
void generateAuxilliaryLayers(wxXmlNode *aCadLayerNode)
wxXmlNode * m_cad_header_node
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)
void pruneUnusedBackdrillSpecs()
std::set< wxUniChar > m_acceptable_chars
void addLayerAttributes(wxXmlNode *aNode, PCB_LAYER_ID aLayer)
wxXmlNode * generateXmlHeader()
Creates the XML header for IPC-2581.
void ensureBackdrillSpecs(const wxString &aPadstackName, const PADSTACK &aPadstack)
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
std::set< wxString > m_backdrill_spec_used
void addLocationNode(wxXmlNode *aContentNode, double aX, double aY)
std::map< int, std::vector< std::pair< wxString, wxString > > > m_net_pin_dict
int m_backdrill_spec_index
std::map< FOOTPRINT *, wxString > m_footprint_refdes_reverse_dict
wxXmlNode * m_lastAppendedNode
Optimization for appendNode to avoid O(n) child traversal.
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.
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_90
@ 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.
surfaceFinishType
IPC-6012 surface finish types from Table 3-3 "Final Finish and Coating Requirements".
@ OTHER
Non-standard finish.
@ DIG
Direct Immersion Gold.
@ HT_OSP
High Temperature OSP.
@ ENEPIG_N
ENEPIG for soldering (normal gold thickness)
@ NONE
No surface finish / not specified - skip coating layer generation.
@ OSP
Organic Solderability Preservative.
@ ENIG_N
ENIG for soldering (normal gold thickness)
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.
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
PAD_DRILL_POST_MACHINING_MODE
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ PTH
Plated through hole pad.
static const std::map< surfaceFinishType, wxString > surfaceFinishTypeToString
Map surfaceFinishType enum to IPC-2581 XML string values.
static bool isOppositeSideSilk(const FOOTPRINT *aFootprint, PCB_LAYER_ID aLayer)
static const std::map< wxString, surfaceFinishType > surfaceFinishMap
Map KiCad surface finish strings to IPC-6012 surfaceFinishType enum.
static surfaceFinishType getSurfaceFinishType(const wxString &aFinish)
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.
! The properties of a padstack drill. Drill position is always the pad position (origin).
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< PAD_DRILL_POST_MACHINING_MODE > mode
@ 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