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() );
166 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
178 static wxXmlNode* lastNode =
nullptr;
180 if( lastNode && lastNode->GetParent() == aParent && lastNode->GetNext() ==
nullptr )
182 aNode->SetParent( aParent );
183 lastNode->SetNext( aNode );
187 aParent->AddChild( aNode );
199 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
213 str.Replace( wxT(
":" ), wxT(
"_" ) );
217 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
234 wxString key = aPrefix ? wxString( aPrefix ) + wxT(
":" ) + aStr : aStr;
244 wxString
name = base;
248 name = wxString::Format(
"%s_%d", base, suffix++ );
264 const char* aPrefix )
const
266 return genString( wxString::Format( wxS(
"%s_%s" ),
268 m_board->GetLayerName( aBottom ) ), aPrefix );
279 if(
name.empty() && fp )
283 if( fp->
Pads()[ii] == aPad )
291 name = wxString::Format(
"NPTH%zu", ii );
292 else if(
name.empty() )
293 name = wxString::Format(
"PAD%zu", ii );
304 [&](
const wxString& aName )
323 wxString
name = baseName;
326 while( !tryInsert(
name ) )
327 name = wxString::Format(
"%s_%d", baseName, suffix++ );
337 wxString str = wxString::FromCDouble( aVal, aSigFig == -1 ?
m_sigfig : aSigFig );
340 while( str.EndsWith( wxT(
"00" ) ) )
344 if( str == wxT(
"-0.0" ) )
369 aNode->AddAttribute( aName, aValue );
375 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
377 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
378 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
379 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
384 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
389 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
394 return xmlHeaderNode;
406 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
414 wxFileName fn(
m_board->GetFileName() );
421 contentNode->AddChild( color_node );
425 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
445 contentNode->AddChild( color_node );
454 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
529 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
533 wxString layer_name = item->GetLayerName();
534 int sub_layer_count = 1;
536 if( layer_name.empty() )
537 layer_name =
m_board->GetLayerName( item->GetBrdLayerId() );
539 layer_name =
genString( layer_name,
"LAYER" );
543 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
545 sub_layer_count = item->GetSublayersCount();
552 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
554 wxString sub_layer_name = layer_name;
557 sub_layer_name += wxString::Format(
"_%d", sub_idx );
559 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
565 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
567 wxXmlNode* color =
appendNode( entry_color,
"Color" );
569 wxString colorName = item->GetColor( sub_idx );
571 if( colorName.StartsWith( wxT(
"#" ) ) )
574 COLOR4D layer_color( colorName );
586 if( fab_color.GetName() == colorName )
588 addAttribute( color,
"r", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).r * 255 ) ) );
589 addAttribute( color,
"g", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).g * 255 ) ) );
590 addAttribute( color,
"b", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).b * 255 ) ) );
610 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
616 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
617 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
624 wxCHECK_RET( aNode,
"aNode is null" );
629 wxXmlNode* entry_node =
nullptr;
633 size_t hash =
lineHash( aWidth, aDashType );
634 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
638 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
653 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
700 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
702 std::list<VECTOR2I> pts;
710 wxXmlNode* line_node =
nullptr;
717 addXY( line_node, pts.front(),
"startX",
"startY" );
718 addXY( line_node, pts.back(),
"endX",
"endY" );
722 line_node =
appendNode( text_node,
"Polyline" );
723 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
724 addXY( point_node, pts.front() );
726 auto iter = pts.begin();
728 for( ++iter; iter != pts.end(); ++iter )
730 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
731 addXY( point_node, *iter );
746 if( aPt1 == pts.back() )
747 pts.push_back( aPt2 );
748 else if( aPt2 == pts.front() )
749 pts.push_front( aPt1 );
750 else if( aPt1 == pts.front() )
751 pts.push_front( aPt2 );
752 else if( aPt2 == pts.back() )
753 pts.push_back( aPt1 );
757 pts.push_back( aPt1 );
758 pts.push_back( aPt2 );
763 pts.push_back( aPt1 );
764 pts.push_back( aPt2 );
770 if( aPoly.PointCount() < 3 )
773 wxXmlNode* outline_node =
appendNode( text_node,
"Outline" );
774 wxXmlNode* poly_node =
appendNode( outline_node,
"Polygon" );
777 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
778 wxXmlNode* point_node =
appendNode( poly_node,
"PolyBegin" );
779 addXY( point_node, pts.front() );
781 for(
size_t ii = 1; ii < pts.size(); ++ii )
783 wxXmlNode* point_node =
785 addXY( point_node, pts[ii] );
788 point_node =
appendNode( poly_node,
"PolyStepSegment" );
789 addXY( point_node, pts.front() );
800 if( text_node->GetChildren() ==
nullptr )
802 aContentNode->RemoveChild( text_node );
815 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
820 int maxError =
m_board->GetDesignSettings().m_MaxError;
840 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
841 circle_node->AddAttribute(
"diameter",
854 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
870 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
886 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
890 roundrect_node->AddAttribute(
"radius",
908 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
913 int shorterSide = std::min( pad_size.
x, pad_size.
y );
944 int dx = pad_size.
x / 2;
945 int dy = pad_size.
y / 2;
946 int ddx = trap_delta.
x / 2;
947 int ddy = trap_delta.
y / 2;
949 outline.
Append( -dx - ddy, dy + ddx );
950 outline.
Append( dx + ddy, dy - ddx );
951 outline.
Append( dx - ddy, -dy + ddx );
952 outline.
Append( -dx + ddy, -dy - ddx );
994 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
1009 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1026 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1034 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1035 addXY( begin_node, start );
1038 wxXmlNode* arc1_node =
appendNode( polyline_node,
"PolyStepCurve" );
1039 addXY( arc1_node, mid );
1044 wxXmlNode* arc2_node =
appendNode( polyline_node,
"PolyStepCurve" );
1045 addXY( arc2_node, start );
1057 int diameter = aShape.
GetRadius() * 2.0;
1064 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1066 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
1092 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1097 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1098 addXY( begin_node, corners[0] );
1100 for(
size_t i = 1; i < corners.size(); ++i )
1102 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1103 addXY( step_node, corners[i] );
1107 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1108 addXY( close_node, corners[0] );
1110 if( stroke_width > 0 )
1111 addLineDesc( polyline_node, stroke_width, dash,
true );
1121 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1128 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1145 width += stroke_width;
1146 height += stroke_width;
1174 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1175 const std::vector<VECTOR2I>& pts = outline.
CPoints();
1177 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1178 addXY( begin_node, pts[0] );
1180 for(
size_t jj = 1; jj < pts.size(); ++jj )
1182 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1183 addXY( step_node, pts[jj] );
1187 if( pts.size() > 2 && pts.front() != pts.back() )
1189 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1190 addXY( close_node, pts[0] );
1193 if( stroke_width > 0 )
1194 addLineDesc( polyline_node, stroke_width, dash,
true );
1208 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1230 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1232 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1249 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1253 std::vector<VECTOR2I> points;
1256 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1257 addXY( point_node, points[0] );
1259 for(
size_t i = 1; i < points.size(); i++ )
1261 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1262 addXY( point_node, points[i] );
1276 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1278 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1294 if( !aInline && !
name.empty() )
1296 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1305 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1325 if( drill_size.
y > drill_size.
x )
1327 std::swap( drill_size.
x, drill_size.
y );
1334 wxXmlNode* xformNode =
appendNode( slotNode,
"Xform" );
1339 wxXmlNode* ovalNode =
appendNode( slotNode,
"Oval" );
1347 int maxError =
m_board->GetDesignSettings().m_MaxError;
1359 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1367 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1369 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1372 return logisticNode;
1383 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1385 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1387 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1388 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1389 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1392 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1395 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1397 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1398 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1421 m_refdes =
new std::vector<REFDES>();
1422 m_props =
new std::map<wxString, wxString>();
1433 wxString m_OEMDesignRef;
1437 wxString m_description;
1439 std::vector<REFDES>* m_refdes;
1440 std::map<wxString, wxString>*
m_props;
1443 std::set<std::unique_ptr<struct BOM_ENTRY>,
1444 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1445 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1446 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1447 const std::unique_ptr<struct BOM_ENTRY>& b )
1449 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1454 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1455 fp->SetParentGroup(
nullptr );
1456 fp->SetPosition( {0, 0} );
1457 fp->SetOrientation(
ANGLE_0 );
1460 if( fp->IsFlipped() )
1468 Report( wxString::Format(
_(
"Footprint %s not found in dictionary; BOM data may be incomplete." ),
1469 fp->GetFPID().GetLibItemName().wx_str() ),
1474 auto entry = std::make_unique<struct BOM_ENTRY>();
1480 entry->m_OEMDesignRef = it->second;
1484 Report( wxString::Format(
_(
"Component \"%s\" missing OEM reference; BOM entry will be skipped." ),
1485 fp->GetFPID().GetLibItemName().wx_str() ),
1489 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1491 entry->m_pads = fp->GetPadCount();
1495 const wxString variantName =
m_board ?
m_board->GetCurrentVariant() : wxString();
1497 if( entry->m_pads == 0 || fp_it->GetExcludedFromBOMForVariant( variantName ) )
1498 entry->m_type =
"DOCUMENT";
1500 entry->m_type =
"ELECTRICAL";
1505 if( descField && !descField->
GetShownText(
false ).IsEmpty() )
1506 entry->m_description = descField->
GetShownText(
false );
1508 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1511 ( *bom_iter )->m_count++;
1515 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1516 refdes.m_populate = !fp->GetDNPForVariant( variantName )
1517 && !fp->GetExcludedFromBOMForVariant( variantName );
1520 ( *bom_iter )->m_refdes->push_back( refdes );
1524 for(
PCB_FIELD* prop : fp->GetFields() )
1529 if( prop->IsMandatory() && !prop->IsValue() )
1532 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetShownText(
false ) );
1536 if( bom_entries.empty() )
1539 wxFileName fn(
m_board->GetFileName() );
1541 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1542 m_xml_root->InsertChild( bomNode, aEcadNode );
1545 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1549 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1552 for(
const auto& entry : bom_entries )
1554 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1555 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1556 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1557 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1558 addAttribute( bomEntryNode,
"category", entry->m_type );
1560 if( !entry->m_description.IsEmpty() )
1561 addAttribute( bomEntryNode,
"description", entry->m_description );
1563 for(
const REFDES& refdes : *( entry->m_refdes ) )
1565 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1568 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1569 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1572 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1573 addAttribute( characteristicsNode,
"category", entry->m_type );
1575 for(
const auto& prop : *( entry->m_props ) )
1577 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1578 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1579 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1580 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1598 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1617 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1618 std::set<PCB_LAYER_ID> added_layers;
1620 for(
int i = 0; i < stackup.
GetCount(); i++ )
1624 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1628 if( ly_name.IsEmpty() )
1637 if( sublayer_id > 0 )
1638 ly_name += wxString::Format(
"_%d", sublayer_id );
1642 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1644 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1646 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1648 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1650 switch ( stackup_item->
GetType() )
1655 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1657 propertyNode =
appendNode( conductorNode,
"Property" );
1658 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1659 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1665 propertyNode =
appendNode( generalNode,
"Property" );
1666 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1668 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1669 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1670 propertyNode =
appendNode( dielectricNode,
"Property" );
1673 dielectricNode =
appendNode( specNode,
"Dielectric" );
1674 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1675 propertyNode =
appendNode( dielectricNode,
"Property" );
1682 propertyNode =
appendNode( generalNode,
"Property" );
1683 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1685 propertyNode =
appendNode( generalNode,
"Property" );
1686 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1692 propertyNode =
appendNode( generalNode,
"Property" );
1693 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1695 propertyNode =
appendNode( generalNode,
"Property" );
1696 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1700 if( stackup_item->
GetEpsilonR( sublayer_id ) > 1.0 )
1702 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1703 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1704 propertyNode =
appendNode( dielectricNode,
"Property" );
1711 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1712 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1713 propertyNode =
appendNode( dielectricNode,
"Property" );
1729 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1732 wxXmlNode* surfaceFinishNode =
appendNode( specNode,
"SurfaceFinish" );
1733 wxXmlNode* finishNode =
appendNode( surfaceFinishNode,
"Finish" );
1745 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1789 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1830 aLayer ==
F_Cu ?
"TOP"
1831 : aLayer ==
B_Cu ?
"BOTTOM"
1849 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1850 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1857 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1859 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1860 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1865 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1866 std::set<PCB_LAYER_ID> added_layers;
1869 for(
int i = 0; i < stackup.
GetCount(); i++ )
1873 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1878 if( hasCoating && layer_id ==
F_Cu && sublayer_id == 0 )
1880 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1881 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_TOP" );
1885 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1887 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1891 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1894 if( ly_name.IsEmpty() )
1903 if( sublayer_id > 0 )
1904 ly_name += wxString::Format(
"_%d", sublayer_id );
1908 wxString spec_name =
genString( ly_name,
"SPEC_LAYER" );
1909 ly_name =
genString( ly_name,
"LAYER" );
1911 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1915 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1917 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1923 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1924 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_BOTTOM" );
1928 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1930 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1945 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1946 std::set<PCB_LAYER_ID> added_layers;
1948 for(
int i = 0; i < stackup.
GetCount(); i++ )
1955 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1957 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1960 if( ly_name.IsEmpty() )
1970 if( sublayer_id > 0 )
1971 ly_name += wxString::Format(
"_%d", sublayer_id );
1975 ly_name =
genString( ly_name,
"LAYER" );
1982 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1984 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1999 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
2008 added_layers.insert( layer );
2009 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2020 wxXmlNode* topCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2022 addAttribute( topCoatingNode,
"layerFunction",
"COATINGCOND" );
2024 addAttribute( topCoatingNode,
"polarity",
"POSITIVE" );
2026 wxXmlNode* botCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2027 addAttribute( botCoatingNode,
"name",
"COATING_BOTTOM" );
2028 addAttribute( botCoatingNode,
"layerFunction",
"COATINGCOND" );
2030 addAttribute( botCoatingNode,
"polarity",
"POSITIVE" );
2048 for(
PAD*
pad : fp->Pads() )
2050 if(
pad->HasDrilledHole() )
2052 else if(
pad->HasHole() )
2059 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2060 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2065 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2072 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2073 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2079 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2095 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
2097 if(
via->Padstack().IsFilled().value_or(
false ) )
2100 if(
via->Padstack().IsCapped().value_or(
false ) )
2105 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
2108 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
2111 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
2115 for(
auto& tuple : new_layers )
2121 bool add_node =
true;
2124 wxString layerFunction;
2127 switch( std::get<0>(layers) )
2131 layerFunction =
"COATINGNONCOND";
2135 layerFunction =
"HOLEFILL";
2139 layerFunction =
"COATINGNONCOND";
2143 layerFunction =
"HOLEFILL";
2147 layerFunction =
"COATINGCOND";
2155 if( add_node && !vec.empty() )
2157 wxXmlNode* node =
appendNode( aCadLayerNode,
"LAYER" );
2171 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
2172 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
2174 if( first_external )
2176 if( second_external )
2183 if( second_external )
2189 wxXmlNode* spanNode =
appendNode( node,
"SPAN" );
2200 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
2201 wxFileName fn(
m_board->GetFileName() );
2207 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
2227 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2234 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
2241 addShape( padNode, *aPad, aLayer );
2245 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
2258 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2279 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
2286 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2301 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2302 padStackHoleNode->AddAttribute(
"name",
2303 wxString::Format(
"%s%d_%d",
2321 if( !
m_board->IsLayerEnabled( layer ) )
2324 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2326 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2334 addShape( padStackPadDefNode, shape );
2338 addShape( padStackPadDefNode, *aPad, layer );
2350 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2357 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2363 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2366 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2375 bool drill ) ->
void
2380 shape.
SetEnd( {
KiROUND( aVia->GetDrillValue() / 2.0 ), 0 } );
2382 shape.
SetEnd( {
KiROUND( aVia->GetWidth( layer ) / 2.0 ), 0 } );
2384 wxXmlNode* padStackPadDefNode =
2385 appendNode( padStackDefNode,
"PadstackPadDef" );
2387 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2390 addShape( padStackPadDefNode, shape );
2410 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2413 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2416 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2431 if( secondary.
size.
x <= 0 && secondary.
size.
y <= 0 )
2442 if( !layerHasRef( secondary.
start ) || !layerHasRef( secondary.
end ) )
2463 wxXmlNode* backdrillNode =
appendNode( specNode,
"Backdrill" );
2464 addAttribute( backdrillNode,
"startLayerRef", startLayer->second );
2465 addAttribute( backdrillNode,
"mustNotCutLayerRef", endLayer->second );
2469 if( stubLength < 0 )
2484 addAttribute( backdrillNode,
"postMachining", isPostMachined ? wxT(
"true" )
2495 wxString primarySpec = createSpec( primary, wxString::Format( wxT(
"BD_%dA" ), specIndex ) );
2497 wxString secondarySpec = createSpec( secondary, wxString::Format( wxT(
"BD_%dB" ), specIndex ) );
2499 if( primarySpec.IsEmpty() && secondarySpec.IsEmpty() )
2514 auto addRef = [&](
const wxString& aSpecName )
2516 if( aSpecName.IsEmpty() )
2519 wxXmlNode* specRefNode =
appendNode( aHoleNode,
"SpecRef" );
2524 addRef( it->second.first );
2525 addRef( it->second.second );
2540 wxXmlNode* specNode = it->second;
2562 wxXmlNode* polygonNode =
nullptr;
2570 polygonNode =
appendNode( aParentNode,
"Polygon" );
2571 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2573 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2574 addXY( polybeginNode, pts[0] );
2576 for(
size_t ii = 1; ii < pts.size(); ++ii )
2578 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2579 addXY( polyNode, pts[ii] );
2582 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2583 addXY( polyendNode, pts[0] );
2594 addLineDesc( polygonNode, aWidth, aDashType,
true );
2598 wxCHECK( aWidth == 0,
false );
2611 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2613 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2615 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2616 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2618 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2619 addXY( polybeginNode, hole[0] );
2621 for(
size_t jj = 1; jj < hole.size(); ++jj )
2623 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2624 addXY( polyNode, hole[jj] );
2627 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2628 addXY( polyendNode, hole[0] );
2641 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2661 outline = &bbox_outline;
2666 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2668 if( !outlineNode->GetChildren() )
2670 aParentNode->RemoveChild( outlineNode );
2687 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2697 aParentNode->RemoveChild( contourNode );
2710 if( !
m_board->GetBoardPolygonOutlines( board_outline,
false ) )
2716 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2720 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2721 aStepNode->RemoveChild( profileNode );
2744 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2745 fp->SetParentGroup(
nullptr );
2746 fp->SetPosition( { 0, 0 } );
2747 fp->SetOrientation(
ANGLE_0 );
2752 bool wasFlipped = fp->IsFlipped();
2755 if( fp->IsFlipped() )
2760 fp->GetFPID().GetLibItemName().wx_str(),
2764 addAttribute( aContentNode,
"packageRef", iter->second );
2771 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2772 wxXmlNode* otherSideViewNode =
nullptr;
2778 if( fp->FindPadByNumber(
"1" ) )
2780 else if ( fp->FindPadByNumber(
"A1" ) )
2782 else if ( fp->FindPadByNumber(
"A" ) )
2784 else if ( fp->FindPadByNumber(
"a" ) )
2786 else if ( fp->FindPadByNumber(
"a1" ) )
2788 else if ( fp->FindPadByNumber(
"Anode" ) )
2790 else if ( fp->FindPadByNumber(
"ANODE" ) )
2795 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2800 : fp->GetCourtyard(
F_CrtYd );
2802 : fp->GetCourtyard(
B_CrtYd );
2812 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2824 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2828 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2830 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2855 elements[item->GetLayer()][is_abs].push_back( item );
2858 auto add_base_node =
2861 wxXmlNode* parent = packageNode;
2870 bool is_other_side = wasFlipped ? ( aLayer ==
F_SilkS || aLayer ==
F_Fab )
2875 if( !otherSideViewNode )
2876 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2878 parent = otherSideViewNode;
2884 name =
"SilkScreen";
2885 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2886 name =
"AssemblyDrawing";
2894 auto add_marking_node =
2895 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2897 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2899 return marking_node;
2902 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2903 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2907 if( elements.find( layer ) != elements.end() )
2909 if( elements[layer][
true].size() > 0 )
2910 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2911 else if( elements[layer][
false].size() > 0 )
2912 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2916 for(
auto& [layer, map] : elements )
2918 wxXmlNode* layer_node = add_base_node( layer );
2919 wxXmlNode* marking_node = add_marking_node( layer_node );
2920 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2921 bool update_bbox =
false;
2925 layer_nodes[layer] = layer_node;
2929 for(
auto& [is_abs, vec] : map )
2933 wxXmlNode* output_node =
nullptr;
2936 layer_bbox[layer].Merge( item->GetBoundingBox() );
2939 output_node = add_marking_node( layer_node );
2941 output_node = group_node;
2943 switch( item->Type() )
2949 if(
text->IsKnockout() )
2963 if(
text->IsBorderEnabled() )
2966 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2968 text->GetBorderWidth() );
2991 if( group_node->GetChildren() ==
nullptr )
2993 marking_node->RemoveChild( group_node );
2994 layer_node->RemoveChild( marking_node );
2996 delete marking_node;
3000 for(
auto&[layer, bbox] : layer_bbox )
3002 if( bbox.GetWidth() > 0 )
3004 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
3007 std::vector<VECTOR2I> points( 4 );
3008 points[0] = bbox.GetPosition();
3009 points[2] = bbox.GetEnd();
3010 points[1].x = points[0].x;
3011 points[1].y = points[2].y;
3012 points[3].x = points[2].x;
3013 points[3].y = points[0].y;
3015 outline.
Append( points );
3021 std::map<wxString, wxXmlNode*> pin_nodes;
3023 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
3025 PAD*
pad = fp->Pads()[ii];
3027 wxXmlNode* pinNode =
nullptr;
3029 auto [ it, inserted ] = pin_nodes.emplace(
name,
nullptr );
3034 it->second = pinNode;
3042 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
3043 else if(
pad->IsOnCopperLayer() )
3044 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
3046 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
3048 if(
pad->HasHole() )
3053 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
3055 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
3056 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
3058 if( fp->IsFlipped() )
3067 pinNode = it->second;
3085 std::vector<wxXmlNode*> componentNodes;
3086 std::vector<wxXmlNode*> packageNodes;
3087 std::set<wxString> packageNames;
3089 bool generate_unique =
m_OEMRef.empty();
3093 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
3095 wxXmlNode* pkg =
addPackage( componentNode, fp );
3098 packageNodes.push_back( pkg );
3104 if( !generate_unique )
3107 if( field && !field->
GetText().empty() )
3113 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
3114 fp->GetFPID().GetLibItemName().wx_str(),
3119 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
3127 else if( fp->GetAttributes() &
FP_SMD )
3132 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
3134 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
3138 if( fp->IsFlipped() )
3144 if( fp->IsFlipped() )
3148 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
3150 componentNodes.push_back( componentNode );
3159 for( wxXmlNode* pkg : packageNodes )
3160 aStepNode->AddChild( pkg );
3162 for( wxXmlNode* cmp : componentNodes )
3163 aStepNode->AddChild( cmp );
3171 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
3173 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
3175 for(
auto& [cmp,
pin] : pin_pair )
3177 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
3191 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
3195 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
3197 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
3198 [&layers, &elements](
PCB_TRACK* aTrack )
3200 if( aTrack->Type() == PCB_VIA_T )
3202 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
3204 for( PCB_LAYER_ID layer : layers )
3206 if( via->FlashLayer( layer ) )
3207 elements[layer][via->GetNetCode()].push_back( via );
3212 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
3216 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
3217 [ &elements ](
ZONE* zone )
3219 LSEQ zone_layers = zone->GetLayerSet().Seq();
3221 for( PCB_LAYER_ID layer : zone_layers )
3222 elements[layer][zone->GetNetCode()].push_back( zone );
3225 for(
BOARD_ITEM* item : m_board->Drawings() )
3228 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
3230 elements[item->GetLayer()][0].push_back( item );
3233 for(
FOOTPRINT* fp : m_board->Footprints() )
3235 for(
PCB_FIELD* field : fp->GetFields() )
3236 elements[field->GetLayer()][0].push_back( field );
3238 for(
BOARD_ITEM* item : fp->GraphicalItems() )
3239 elements[item->GetLayer()][0].push_back( item );
3241 for(
PAD*
pad : fp->Pads() )
3243 LSEQ pad_layers =
pad->GetLayerSet().Seq();
3247 if(
pad->FlashLayer( layer ) )
3248 elements[layer][
pad->GetNetCode()].push_back(
pad );
3255 if( m_progressReporter )
3256 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
3258 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
3259 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
3261 auto process_net = [&] (
int net )
3263 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
3268 std::stable_sort( vec.begin(), vec.end(),
3271 if( a->GetParentFootprint() == b->GetParentFootprint() )
3272 return a->Type() < b->Type();
3274 return a->GetParentFootprint() < b->GetParentFootprint();
3277 generateLayerSetNet( layerNode, layer, vec );
3282 if( m_progressReporter )
3284 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
3285 m_board->GetLayerName( layer ),
3286 net->GetNetname() ) );
3287 m_progressReporter->AdvanceProgress();
3290 process_net( net->GetNetCode() );
3293 if( layerNode->GetChildren() ==
nullptr )
3295 aStepNode->RemoveChild( layerNode );
3308 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3309 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
3320 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
3325 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3328 if(
via->GetNetCode() > 0 )
3331 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3332 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3337 addXY( holeNode,
via->GetPosition() );
3347 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
3352 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3355 if(
pad->GetNetCode() > 0 )
3358 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3359 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3365 addXY( holeNode,
pad->GetPosition() );
3375 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3376 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
3380 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3382 if(
pad->GetNetCode() > 0 )
3385 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
3392 std::vector<BOARD_ITEM*>& aItems )
3394 auto it = aItems.begin();
3395 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
3396 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
3397 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
3399 bool has_via =
false;
3400 bool has_pad =
false;
3402 wxXmlNode* padSetNode =
nullptr;
3404 wxXmlNode* viaSetNode =
nullptr;
3406 wxXmlNode* teardropLayerSetNode =
nullptr;
3407 wxXmlNode* teardropFeatureSetNode =
nullptr;
3409 bool teardrop_warning =
false;
3414 if( item->GetNetCode() > 0 )
3424 shape.
SetStart( track->GetStart() );
3425 shape.
SetEnd( track->GetEnd() );
3426 shape.
SetWidth( track->GetWidth() );
3443 viaSetNode = layerSetNode;
3448 viaSetNode =
appendNode( layerSetNode,
"Set" );
3450 if( track->GetNetCode() > 0 )
3457 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
3464 wxXmlNode* zoneFeatureNode = specialNode;
3466 if( zone->IsTeardropArea() )
3470 if( !teardropFeatureSetNode )
3472 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
3473 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
3475 if( zone->GetNetCode() > 0 )
3478 genString( zone->GetNetname(),
"NET" ) );
3481 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3483 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3486 zoneFeatureNode = teardropFeatureSetNode;
3488 else if( !teardrop_warning )
3490 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3492 teardrop_warning =
true;
3499 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3500 wxString refDes =
componentName( zone->GetParentFootprint() );
3502 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3504 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3508 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3510 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3521 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3524 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3526 bool link_to_component =
true;
3529 link_to_component =
false;
3531 if( link_to_component )
3534 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3541 wxXmlNode* xformNode =
appendNode( tempFeature,
"Xform" );
3552 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3554 if( shape->GetNetCode() > 0 )
3557 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3574 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3576 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3581 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3586 bool link_to_component = fp !=
nullptr;
3589 link_to_component =
false;
3591 if( link_to_component )
3594 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3595 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3597 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3599 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3605 addText( tempFeature, text_item,
text->GetFontMetrics() );
3623 padSetNode = layerSetNode;
3628 padSetNode =
appendNode( aLayerNode,
"Set" );
3630 if(
pad->GetNetCode() > 0 )
3645 switch( item->Type() )
3650 add_track(
static_cast<PCB_TRACK*
>( item ) );
3658 add_pad(
static_cast<PAD*
>( item ) );
3662 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3687 if( specialNode->GetChildren() ==
nullptr )
3689 featureSetNode->RemoveChild( specialNode );
3693 if( featureSetNode->GetChildren() ==
nullptr )
3695 layerSetNode->RemoveChild( featureSetNode );
3696 delete featureSetNode;
3699 if( layerSetNode->GetChildren() ==
nullptr )
3701 aLayerNode->RemoveChild( layerSetNode );
3702 delete layerSetNode;
3713 bool add_node =
true;
3719 switch( std::get<0>(layers) )
3748 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3752 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3766 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3768 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3792 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3796 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3799 std::set<wxString> unique_parts;
3800 std::map<wxString,wxString> unique_vendors;
3804 auto [ it, success ] = unique_parts.insert(
name );
3809 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3816 for (
int ii = 0; ii < 2; ++ii )
3822 if( mpn_name.empty() )
3825 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3829 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3832 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3834 wxString
name = wxT(
"UNKNOWN" );
3837 if( !ii && company[ii] )
3845 else if( !ii && !company_name[ii].
empty() )
3847 name = company_name[ii];
3849 else if( ii && !
m_dist.empty() )
3854 auto [vendor_id, inserted] = unique_vendors.emplace(
3856 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3858 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3862 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3878 const std::map<std::string, UTF8>* aProperties )
3920 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3922 if( it->second ==
"inch" )
3929 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3930 m_sigfig = std::stoi( it->second );
3932 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3935 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3938 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3939 m_mpn = it->second.wx_str();
3941 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3942 m_mfg = it->second.wx_str();
3944 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3945 m_dist = it->second.wx_str();
3947 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3952 for(
char c =
'a'; c <=
'z'; ++c )
3955 for(
char c =
'A'; c <=
'Z'; ++c )
3958 for(
char c =
'0'; c <=
'9'; ++c )
3962 std::string specialChars =
"_\\-.+><";
3964 for(
char c : specialChars )
3993 double written_bytes = 0.0;
3994 double last_yield = 0.0;
4001 auto update_progress = [&](
size_t aBytes )
4003 written_bytes += aBytes;
4004 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
4009 if( last_yield + 0.01 < percent )
4011 last_yield = percent;
4025 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)
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_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