48#include <wx/numformatter.h>
49#include <wx/xml/xml.h>
129 std::vector<FOOTPRINT*> retval;
132 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
142 if( aParent->GetChildren() )
143 aNode->SetNext( aParent->GetChildren() );
145 aNode->SetNext(
nullptr );
147 aParent->SetChildren( aNode );
148 aNode->SetParent( aParent );
157 aNode->SetNext( aPrev->GetNext() );
158 aPrev->SetNext( aNode );
159 aNode->SetParent( aPrev->GetParent() );
180 check = check->GetParent();
193 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
208 aNode->SetParent( aParent );
213 aParent->AddChild( aNode );
225 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
239 str.Replace( wxT(
":" ), wxT(
"_" ) );
243 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
260 wxString key = aPrefix ? wxString( aPrefix ) + wxT(
":" ) + aStr : aStr;
270 wxString
name = base;
274 name = wxString::Format(
"%s_%d", base, suffix++ );
290 const char* aPrefix )
const
292 return genString( wxString::Format( wxS(
"%s_%s" ),
294 m_board->GetLayerName( aBottom ) ), aPrefix );
305 if(
name.empty() && fp )
309 if( fp->
Pads()[ii] == aPad )
317 name = wxString::Format(
"NPTH%zu", ii );
318 else if(
name.empty() )
319 name = wxString::Format(
"PAD%zu", ii );
330 [&](
const wxString& aName )
349 wxString
name = baseName;
352 while( !tryInsert(
name ) )
353 name = wxString::Format(
"%s_%d", baseName, suffix++ );
363 wxString str = wxString::FromCDouble( aVal, aSigFig == -1 ?
m_sigfig : aSigFig );
366 while( str.EndsWith( wxT(
"00" ) ) )
370 if( str == wxT(
"-0.0" ) )
395 aNode->AddAttribute( aName, aValue );
401 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
403 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
404 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
405 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
410 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
415 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
420 return xmlHeaderNode;
432 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
440 wxFileName fn(
m_board->GetFileName() );
447 contentNode->AddChild( color_node );
451 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
471 contentNode->AddChild( color_node );
480 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
555 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
559 wxString layer_name = item->GetLayerName();
560 int sub_layer_count = 1;
562 if( layer_name.empty() )
563 layer_name =
m_board->GetLayerName( item->GetBrdLayerId() );
565 layer_name =
genString( layer_name,
"LAYER" );
569 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
571 sub_layer_count = item->GetSublayersCount();
578 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
580 wxString sub_layer_name = layer_name;
583 sub_layer_name += wxString::Format(
"_%d", sub_idx );
585 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
591 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
593 wxXmlNode* color =
appendNode( entry_color,
"Color" );
595 wxString colorName = item->GetColor( sub_idx );
597 if( colorName.StartsWith( wxT(
"#" ) ) )
600 COLOR4D layer_color( colorName );
612 if( fab_color.GetName() == colorName )
614 addAttribute( color,
"r", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).r * 255 ) ) );
615 addAttribute( color,
"g", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).g * 255 ) ) );
616 addAttribute( color,
"b", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).b * 255 ) ) );
636 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
642 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
643 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
650 wxCHECK_RET( aNode,
"aNode is null" );
655 wxXmlNode* entry_node =
nullptr;
659 size_t hash =
lineHash( aWidth, aDashType );
660 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
664 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
679 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
726 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
728 std::list<VECTOR2I> pts;
736 wxXmlNode* line_node =
nullptr;
743 addXY( line_node, pts.front(),
"startX",
"startY" );
744 addXY( line_node, pts.back(),
"endX",
"endY" );
748 line_node =
appendNode( text_node,
"Polyline" );
749 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
750 addXY( point_node, pts.front() );
752 auto iter = pts.begin();
754 for( ++iter; iter != pts.end(); ++iter )
756 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
757 addXY( point_node, *iter );
772 if( aPt1 == pts.back() )
773 pts.push_back( aPt2 );
774 else if( aPt2 == pts.front() )
775 pts.push_front( aPt1 );
776 else if( aPt1 == pts.front() )
777 pts.push_front( aPt2 );
778 else if( aPt2 == pts.back() )
779 pts.push_back( aPt1 );
783 pts.push_back( aPt1 );
784 pts.push_back( aPt2 );
789 pts.push_back( aPt1 );
790 pts.push_back( aPt2 );
796 if( aPoly.PointCount() < 3 )
799 wxXmlNode* outline_node =
appendNode( text_node,
"Outline" );
800 wxXmlNode* poly_node =
appendNode( outline_node,
"Polygon" );
803 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
804 wxXmlNode* point_node =
appendNode( poly_node,
"PolyBegin" );
805 addXY( point_node, pts.front() );
807 for(
size_t ii = 1; ii < pts.size(); ++ii )
809 wxXmlNode* point_node =
811 addXY( point_node, pts[ii] );
814 point_node =
appendNode( poly_node,
"PolyStepSegment" );
815 addXY( point_node, pts.front() );
826 if( text_node->GetChildren() ==
nullptr )
828 aContentNode->RemoveChild( text_node );
841 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
846 int maxError =
m_board->GetDesignSettings().m_MaxError;
866 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
867 circle_node->AddAttribute(
"diameter",
880 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
896 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
912 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
916 roundrect_node->AddAttribute(
"radius",
934 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
939 int shorterSide = std::min( pad_size.
x, pad_size.
y );
970 int dx = pad_size.
x / 2;
971 int dy = pad_size.
y / 2;
972 int ddx = trap_delta.
x / 2;
973 int ddy = trap_delta.
y / 2;
975 outline.
Append( -dx - ddy, dy + ddx );
976 outline.
Append( dx + ddy, dy - ddx );
977 outline.
Append( dx - ddy, -dy + ddx );
978 outline.
Append( -dx + ddy, -dy - ddx );
1003 if( expansion !=
VECTOR2I( 0, 0 ) )
1020 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
1035 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1052 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1060 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1061 addXY( begin_node, start );
1064 wxXmlNode* arc1_node =
appendNode( polyline_node,
"PolyStepCurve" );
1065 addXY( arc1_node, mid );
1070 wxXmlNode* arc2_node =
appendNode( polyline_node,
"PolyStepCurve" );
1071 addXY( arc2_node, start );
1083 int diameter = aShape.
GetRadius() * 2.0;
1090 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1092 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
1118 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1123 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1124 addXY( begin_node, corners[0] );
1126 for(
size_t i = 1; i < corners.size(); ++i )
1128 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1129 addXY( step_node, corners[i] );
1133 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1134 addXY( close_node, corners[0] );
1136 if( stroke_width > 0 )
1137 addLineDesc( polyline_node, stroke_width, dash,
true );
1147 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1154 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1171 width += stroke_width;
1172 height += stroke_width;
1200 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1201 const std::vector<VECTOR2I>& pts = outline.
CPoints();
1203 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1204 addXY( begin_node, pts[0] );
1206 for(
size_t jj = 1; jj < pts.size(); ++jj )
1208 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1209 addXY( step_node, pts[jj] );
1213 if( pts.size() > 2 && pts.front() != pts.back() )
1215 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1216 addXY( close_node, pts[0] );
1219 if( stroke_width > 0 )
1220 addLineDesc( polyline_node, stroke_width, dash,
true );
1234 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1256 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1258 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1275 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1279 std::vector<VECTOR2I> points;
1282 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1283 addXY( point_node, points[0] );
1285 for(
size_t i = 1; i < points.size(); i++ )
1287 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1288 addXY( point_node, points[i] );
1302 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1304 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1320 if( !aInline && !
name.empty() )
1322 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1331 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1351 if( drill_size.
y > drill_size.
x )
1353 std::swap( drill_size.
x, drill_size.
y );
1360 wxXmlNode* xformNode =
appendNode( slotNode,
"Xform" );
1365 wxXmlNode* ovalNode =
appendNode( slotNode,
"Oval" );
1373 int maxError =
m_board->GetDesignSettings().m_MaxError;
1385 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1393 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1395 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1398 return logisticNode;
1409 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1411 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1413 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1414 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1415 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1418 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1421 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1423 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1424 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1447 m_refdes =
new std::vector<REFDES>();
1448 m_props =
new std::map<wxString, wxString>();
1459 wxString m_OEMDesignRef;
1463 wxString m_description;
1465 std::vector<REFDES>* m_refdes;
1466 std::map<wxString, wxString>*
m_props;
1469 std::set<std::unique_ptr<struct BOM_ENTRY>,
1470 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1471 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1472 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1473 const std::unique_ptr<struct BOM_ENTRY>& b )
1475 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1480 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1481 fp->SetParentGroup(
nullptr );
1482 fp->SetPosition( {0, 0} );
1483 fp->SetOrientation(
ANGLE_0 );
1486 if( fp->IsFlipped() )
1494 Report( wxString::Format(
_(
"Footprint %s not found in dictionary; BOM data may be incomplete." ),
1495 fp->GetFPID().GetLibItemName().wx_str() ),
1500 auto entry = std::make_unique<struct BOM_ENTRY>();
1506 entry->m_OEMDesignRef = it->second;
1510 Report( wxString::Format(
_(
"Component \"%s\" missing OEM reference; BOM entry will be skipped." ),
1511 fp->GetFPID().GetLibItemName().wx_str() ),
1515 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1517 entry->m_pads = fp->GetPadCount();
1521 const wxString variantName =
m_board ?
m_board->GetCurrentVariant() : wxString();
1523 if( entry->m_pads == 0 || fp_it->GetExcludedFromBOMForVariant( variantName ) )
1524 entry->m_type =
"DOCUMENT";
1526 entry->m_type =
"ELECTRICAL";
1531 if( descField && !descField->
GetShownText(
false ).IsEmpty() )
1532 entry->m_description = descField->
GetShownText(
false );
1534 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1537 ( *bom_iter )->m_count++;
1541 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1542 refdes.m_populate = !fp->GetDNPForVariant( variantName )
1543 && !fp->GetExcludedFromBOMForVariant( variantName );
1546 ( *bom_iter )->m_refdes->push_back( refdes );
1550 for(
PCB_FIELD* prop : fp->GetFields() )
1555 if( prop->IsMandatory() && !prop->IsValue() )
1558 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetShownText(
false ) );
1562 if( bom_entries.empty() )
1565 wxFileName fn(
m_board->GetFileName() );
1567 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1568 m_xml_root->InsertChild( bomNode, aEcadNode );
1571 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1575 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1578 for(
const auto& entry : bom_entries )
1580 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1581 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1582 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1583 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1584 addAttribute( bomEntryNode,
"category", entry->m_type );
1586 if( !entry->m_description.IsEmpty() )
1587 addAttribute( bomEntryNode,
"description", entry->m_description );
1589 for(
const REFDES& refdes : *( entry->m_refdes ) )
1591 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1594 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1595 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1598 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1599 addAttribute( characteristicsNode,
"category", entry->m_type );
1601 for(
const auto& prop : *( entry->m_props ) )
1603 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1604 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1605 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1606 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1624 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1643 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1644 std::set<PCB_LAYER_ID> added_layers;
1646 for(
int i = 0; i < stackup.
GetCount(); i++ )
1650 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1654 if( ly_name.IsEmpty() )
1663 if( sublayer_id > 0 )
1664 ly_name += wxString::Format(
"_%d", sublayer_id );
1668 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1670 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1672 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1674 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1676 switch ( stackup_item->
GetType() )
1681 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1683 propertyNode =
appendNode( conductorNode,
"Property" );
1684 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1685 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1691 propertyNode =
appendNode( generalNode,
"Property" );
1692 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1694 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1695 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1696 propertyNode =
appendNode( dielectricNode,
"Property" );
1699 dielectricNode =
appendNode( specNode,
"Dielectric" );
1700 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1701 propertyNode =
appendNode( dielectricNode,
"Property" );
1708 propertyNode =
appendNode( generalNode,
"Property" );
1709 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1711 propertyNode =
appendNode( generalNode,
"Property" );
1712 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1718 propertyNode =
appendNode( generalNode,
"Property" );
1719 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1721 propertyNode =
appendNode( generalNode,
"Property" );
1722 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1726 if( stackup_item->
GetEpsilonR( sublayer_id ) > 1.0 )
1728 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1729 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1730 propertyNode =
appendNode( dielectricNode,
"Property" );
1737 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1738 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1739 propertyNode =
appendNode( dielectricNode,
"Property" );
1755 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1758 wxXmlNode* surfaceFinishNode =
appendNode( specNode,
"SurfaceFinish" );
1759 wxXmlNode* finishNode =
appendNode( surfaceFinishNode,
"Finish" );
1771 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1815 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1856 aLayer ==
F_Cu ?
"TOP"
1857 : aLayer ==
B_Cu ?
"BOTTOM"
1875 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1876 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1883 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1885 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1886 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1891 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1892 std::set<PCB_LAYER_ID> added_layers;
1895 for(
int i = 0; i < stackup.
GetCount(); i++ )
1899 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1904 if( hasCoating && layer_id ==
F_Cu && sublayer_id == 0 )
1906 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1907 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_TOP" );
1911 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1913 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1917 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1920 if( ly_name.IsEmpty() )
1929 if( sublayer_id > 0 )
1930 ly_name += wxString::Format(
"_%d", sublayer_id );
1934 wxString spec_name =
genString( ly_name,
"SPEC_LAYER" );
1935 ly_name =
genString( ly_name,
"LAYER" );
1937 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1941 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1943 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1949 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1950 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_BOTTOM" );
1954 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1956 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1971 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1972 std::set<PCB_LAYER_ID> added_layers;
1974 for(
int i = 0; i < stackup.
GetCount(); i++ )
1981 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1983 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1986 if( ly_name.IsEmpty() )
1996 if( sublayer_id > 0 )
1997 ly_name += wxString::Format(
"_%d", sublayer_id );
2001 ly_name =
genString( ly_name,
"LAYER" );
2008 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
2010 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
2025 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
2034 added_layers.insert( layer );
2035 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2046 wxXmlNode* topCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2048 addAttribute( topCoatingNode,
"layerFunction",
"COATINGCOND" );
2050 addAttribute( topCoatingNode,
"polarity",
"POSITIVE" );
2052 wxXmlNode* botCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2053 addAttribute( botCoatingNode,
"name",
"COATING_BOTTOM" );
2054 addAttribute( botCoatingNode,
"layerFunction",
"COATINGCOND" );
2056 addAttribute( botCoatingNode,
"polarity",
"POSITIVE" );
2074 for(
PAD*
pad : fp->Pads() )
2076 if(
pad->HasDrilledHole() )
2078 else if(
pad->HasHole() )
2085 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2086 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2091 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2098 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2099 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2105 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2121 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
2123 if(
via->Padstack().IsFilled().value_or(
false ) )
2126 if(
via->Padstack().IsCapped().value_or(
false ) )
2131 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
2134 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
2137 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
2141 for(
auto& tuple : new_layers )
2147 bool add_node =
true;
2150 wxString layerFunction;
2153 switch( std::get<0>(layers) )
2157 layerFunction =
"COATINGNONCOND";
2161 layerFunction =
"HOLEFILL";
2165 layerFunction =
"COATINGNONCOND";
2169 layerFunction =
"HOLEFILL";
2173 layerFunction =
"COATINGCOND";
2181 if( add_node && !vec.empty() )
2183 wxXmlNode* node =
appendNode( aCadLayerNode,
"LAYER" );
2197 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
2198 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
2200 if( first_external )
2202 if( second_external )
2209 if( second_external )
2215 wxXmlNode* spanNode =
appendNode( node,
"SPAN" );
2226 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
2227 wxFileName fn(
m_board->GetFileName() );
2233 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
2253 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2260 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
2267 addShape( padNode, *aPad, aLayer );
2271 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
2284 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2305 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
2312 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2327 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2328 padStackHoleNode->AddAttribute(
"name",
2329 wxString::Format(
"%s%d_%d",
2347 if( !
m_board->IsLayerEnabled( layer ) )
2350 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2352 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2360 addShape( padStackPadDefNode, shape );
2364 addShape( padStackPadDefNode, *aPad, layer );
2376 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2383 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2389 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2392 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2401 bool drill ) ->
void
2406 shape.
SetEnd( {
KiROUND( aVia->GetDrillValue() / 2.0 ), 0 } );
2408 shape.
SetEnd( {
KiROUND( aVia->GetWidth( layer ) / 2.0 ), 0 } );
2410 wxXmlNode* padStackPadDefNode =
2411 appendNode( padStackDefNode,
"PadstackPadDef" );
2413 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2416 addShape( padStackPadDefNode, shape );
2436 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2439 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2442 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2457 if( secondary.
size.
x <= 0 && secondary.
size.
y <= 0 )
2468 if( !layerHasRef( secondary.
start ) || !layerHasRef( secondary.
end ) )
2489 wxXmlNode* backdrillNode =
appendNode( specNode,
"Backdrill" );
2490 addAttribute( backdrillNode,
"startLayerRef", startLayer->second );
2491 addAttribute( backdrillNode,
"mustNotCutLayerRef", endLayer->second );
2495 if( stubLength < 0 )
2510 addAttribute( backdrillNode,
"postMachining", isPostMachined ? wxT(
"true" )
2521 wxString primarySpec = createSpec( primary, wxString::Format( wxT(
"BD_%dA" ), specIndex ) );
2523 wxString secondarySpec = createSpec( secondary, wxString::Format( wxT(
"BD_%dB" ), specIndex ) );
2525 if( primarySpec.IsEmpty() && secondarySpec.IsEmpty() )
2540 auto addRef = [&](
const wxString& aSpecName )
2542 if( aSpecName.IsEmpty() )
2545 wxXmlNode* specRefNode =
appendNode( aHoleNode,
"SpecRef" );
2550 addRef( it->second.first );
2551 addRef( it->second.second );
2566 wxXmlNode* specNode = it->second;
2588 wxXmlNode* polygonNode =
nullptr;
2596 polygonNode =
appendNode( aParentNode,
"Polygon" );
2597 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2599 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2600 addXY( polybeginNode, pts[0] );
2602 for(
size_t ii = 1; ii < pts.size(); ++ii )
2604 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2605 addXY( polyNode, pts[ii] );
2608 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2609 addXY( polyendNode, pts[0] );
2620 addLineDesc( polygonNode, aWidth, aDashType,
true );
2624 wxCHECK( aWidth == 0,
false );
2637 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2639 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2641 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2642 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2644 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2645 addXY( polybeginNode, hole[0] );
2647 for(
size_t jj = 1; jj < hole.size(); ++jj )
2649 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2650 addXY( polyNode, hole[jj] );
2653 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2654 addXY( polyendNode, hole[0] );
2667 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2687 outline = &bbox_outline;
2692 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2694 if( !outlineNode->GetChildren() )
2696 aParentNode->RemoveChild( outlineNode );
2713 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2723 aParentNode->RemoveChild( contourNode );
2736 if( !
m_board->GetBoardPolygonOutlines( board_outline,
false ) )
2742 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2746 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2747 aStepNode->RemoveChild( profileNode );
2770 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2771 fp->SetParentGroup(
nullptr );
2772 fp->SetPosition( { 0, 0 } );
2773 fp->SetOrientation(
ANGLE_0 );
2778 bool wasFlipped = fp->IsFlipped();
2781 if( fp->IsFlipped() )
2786 fp->GetFPID().GetLibItemName().wx_str(),
2790 addAttribute( aContentNode,
"packageRef", iter->second );
2797 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2798 wxXmlNode* otherSideViewNode =
nullptr;
2804 if( fp->FindPadByNumber(
"1" ) )
2806 else if ( fp->FindPadByNumber(
"A1" ) )
2808 else if ( fp->FindPadByNumber(
"A" ) )
2810 else if ( fp->FindPadByNumber(
"a" ) )
2812 else if ( fp->FindPadByNumber(
"a1" ) )
2814 else if ( fp->FindPadByNumber(
"Anode" ) )
2816 else if ( fp->FindPadByNumber(
"ANODE" ) )
2821 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2826 : fp->GetCourtyard(
F_CrtYd );
2828 : fp->GetCourtyard(
B_CrtYd );
2838 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2850 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2854 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2856 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2881 elements[item->GetLayer()][is_abs].push_back( item );
2884 auto add_base_node =
2887 wxXmlNode* parent = packageNode;
2896 bool is_other_side = wasFlipped ? ( aLayer ==
F_SilkS || aLayer ==
F_Fab )
2901 if( !otherSideViewNode )
2902 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2904 parent = otherSideViewNode;
2910 name =
"SilkScreen";
2911 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2912 name =
"AssemblyDrawing";
2920 auto add_marking_node =
2921 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2923 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2925 return marking_node;
2928 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2929 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2933 if( elements.find( layer ) != elements.end() )
2935 if( elements[layer][
true].size() > 0 )
2936 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2937 else if( elements[layer][
false].size() > 0 )
2938 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2942 for(
auto& [layer, map] : elements )
2944 wxXmlNode* layer_node = add_base_node( layer );
2945 wxXmlNode* marking_node = add_marking_node( layer_node );
2946 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2947 bool update_bbox =
false;
2951 layer_nodes[layer] = layer_node;
2955 for(
auto& [is_abs, vec] : map )
2959 wxXmlNode* output_node =
nullptr;
2962 layer_bbox[layer].Merge( item->GetBoundingBox() );
2965 output_node = add_marking_node( layer_node );
2967 output_node = group_node;
2969 switch( item->Type() )
2975 if(
text->IsKnockout() )
2989 if(
text->IsBorderEnabled() )
2992 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2994 text->GetBorderWidth() );
3017 if( group_node->GetChildren() ==
nullptr )
3019 marking_node->RemoveChild( group_node );
3020 layer_node->RemoveChild( marking_node );
3022 delete marking_node;
3026 for(
auto&[layer, bbox] : layer_bbox )
3028 if( bbox.GetWidth() > 0 )
3030 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
3033 std::vector<VECTOR2I> points( 4 );
3034 points[0] = bbox.GetPosition();
3035 points[2] = bbox.GetEnd();
3036 points[1].x = points[0].x;
3037 points[1].y = points[2].y;
3038 points[3].x = points[2].x;
3039 points[3].y = points[0].y;
3041 outline.
Append( points );
3047 std::map<wxString, wxXmlNode*> pin_nodes;
3049 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
3051 PAD*
pad = fp->Pads()[ii];
3053 wxXmlNode* pinNode =
nullptr;
3055 auto [ it, inserted ] = pin_nodes.emplace(
name,
nullptr );
3060 it->second = pinNode;
3068 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
3069 else if(
pad->IsOnCopperLayer() )
3070 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
3072 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
3074 if(
pad->HasHole() )
3079 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
3081 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
3082 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
3084 if( fp->IsFlipped() )
3107 std::vector<wxXmlNode*> componentNodes;
3108 std::vector<wxXmlNode*> packageNodes;
3109 std::set<wxString> packageNames;
3111 bool generate_unique =
m_OEMRef.empty();
3115 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
3117 wxXmlNode* pkg =
addPackage( componentNode, fp );
3120 packageNodes.push_back( pkg );
3126 if( !generate_unique )
3129 if( field && !field->
GetText().empty() )
3135 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
3136 fp->GetFPID().GetLibItemName().wx_str(),
3141 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
3149 else if( fp->GetAttributes() &
FP_SMD )
3154 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
3156 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
3160 if( fp->IsFlipped() )
3166 if( fp->IsFlipped() )
3170 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
3172 componentNodes.push_back( componentNode );
3181 for( wxXmlNode* pkg : packageNodes )
3182 aStepNode->AddChild( pkg );
3184 for( wxXmlNode* cmp : componentNodes )
3185 aStepNode->AddChild( cmp );
3193 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
3195 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
3197 for(
auto& [cmp,
pin] : pin_pair )
3199 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
3213 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
3217 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
3219 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
3220 [&layers, &elements](
PCB_TRACK* aTrack )
3222 if( aTrack->Type() == PCB_VIA_T )
3224 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
3226 for( PCB_LAYER_ID layer : layers )
3228 if( via->FlashLayer( layer ) )
3229 elements[layer][via->GetNetCode()].push_back( via );
3234 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
3238 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
3239 [ &elements ](
ZONE* zone )
3241 LSEQ zone_layers = zone->GetLayerSet().Seq();
3243 for( PCB_LAYER_ID layer : zone_layers )
3244 elements[layer][zone->GetNetCode()].push_back( zone );
3247 for(
BOARD_ITEM* item : m_board->Drawings() )
3250 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
3252 elements[item->GetLayer()][0].push_back( item );
3255 for(
FOOTPRINT* fp : m_board->Footprints() )
3257 for(
PCB_FIELD* field : fp->GetFields() )
3258 elements[field->GetLayer()][0].push_back( field );
3260 for(
BOARD_ITEM* item : fp->GraphicalItems() )
3261 elements[item->GetLayer()][0].push_back( item );
3263 for(
PAD*
pad : fp->Pads() )
3265 LSEQ pad_layers =
pad->GetLayerSet().Seq();
3269 if(
pad->FlashLayer( layer ) )
3270 elements[layer][
pad->GetNetCode()].push_back(
pad );
3297 if( m_progressReporter )
3298 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
3300 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
3301 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
3303 auto process_net = [&] (
int net )
3305 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
3310 std::stable_sort( vec.begin(), vec.end(),
3313 if( a->GetParentFootprint() == b->GetParentFootprint() )
3314 return a->Type() < b->Type();
3316 return a->GetParentFootprint() < b->GetParentFootprint();
3319 generateLayerSetNet( layerNode, layer, vec );
3324 if( m_progressReporter )
3326 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
3327 m_board->GetLayerName( layer ),
3328 net->GetNetname() ) );
3329 m_progressReporter->AdvanceProgress();
3332 process_net( net->GetNetCode() );
3335 if( layerNode->GetChildren() ==
nullptr )
3337 aStepNode->RemoveChild( layerNode );
3338 deleteNode( layerNode );
3350 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3351 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
3362 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
3367 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3370 if(
via->GetNetCode() > 0 )
3373 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3374 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3379 addXY( holeNode,
via->GetPosition() );
3389 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
3394 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3397 if(
pad->GetNetCode() > 0 )
3400 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3401 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3407 addXY( holeNode,
pad->GetPosition() );
3417 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3418 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
3422 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3424 if(
pad->GetNetCode() > 0 )
3427 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
3434 std::vector<BOARD_ITEM*>& aItems )
3436 auto it = aItems.begin();
3437 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
3438 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
3439 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
3441 bool has_via =
false;
3442 bool has_pad =
false;
3444 wxXmlNode* padSetNode =
nullptr;
3446 wxXmlNode* viaSetNode =
nullptr;
3448 wxXmlNode* teardropLayerSetNode =
nullptr;
3449 wxXmlNode* teardropFeatureSetNode =
nullptr;
3451 bool teardrop_warning =
false;
3456 if( item->GetNetCode() > 0 )
3466 shape.
SetStart( track->GetStart() );
3467 shape.
SetEnd( track->GetEnd() );
3468 shape.
SetWidth( track->GetWidth() );
3485 viaSetNode = layerSetNode;
3490 viaSetNode =
appendNode( layerSetNode,
"Set" );
3492 if( track->GetNetCode() > 0 )
3499 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
3506 wxXmlNode* zoneFeatureNode = specialNode;
3508 if( zone->IsTeardropArea() )
3512 if( !teardropFeatureSetNode )
3514 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
3515 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
3517 if( zone->GetNetCode() > 0 )
3520 genString( zone->GetNetname(),
"NET" ) );
3523 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3525 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3528 zoneFeatureNode = teardropFeatureSetNode;
3530 else if( !teardrop_warning )
3532 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3534 teardrop_warning =
true;
3541 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3542 wxString refDes =
componentName( zone->GetParentFootprint() );
3544 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3546 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3550 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3552 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3563 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3566 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3568 bool link_to_component =
true;
3571 link_to_component =
false;
3573 if( link_to_component )
3576 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3583 wxXmlNode* xformNode =
appendNode( tempFeature,
"Xform" );
3594 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3596 if( shape->GetNetCode() > 0 )
3599 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3616 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3618 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
3623 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3628 bool link_to_component = fp !=
nullptr;
3631 link_to_component =
false;
3633 if( link_to_component )
3636 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3637 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3639 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3641 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3647 addText( tempFeature, text_item,
text->GetFontMetrics() );
3665 padSetNode = layerSetNode;
3670 padSetNode =
appendNode( aLayerNode,
"Set" );
3672 if(
pad->GetNetCode() > 0 )
3687 switch( item->Type() )
3692 add_track(
static_cast<PCB_TRACK*
>( item ) );
3700 add_pad(
static_cast<PAD*
>( item ) );
3704 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3729 if( specialNode->GetChildren() ==
nullptr )
3731 featureSetNode->RemoveChild( specialNode );
3735 if( featureSetNode->GetChildren() ==
nullptr )
3737 layerSetNode->RemoveChild( featureSetNode );
3741 if( layerSetNode->GetChildren() ==
nullptr )
3743 aLayerNode->RemoveChild( layerSetNode );
3755 bool add_node =
true;
3761 switch( std::get<0>(layers) )
3790 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3794 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3808 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3810 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3834 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3838 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3841 std::set<wxString> unique_parts;
3842 std::map<wxString,wxString> unique_vendors;
3846 auto [ it, success ] = unique_parts.insert(
name );
3851 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3858 for (
int ii = 0; ii < 2; ++ii )
3864 if( mpn_name.empty() )
3867 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3871 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3874 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3876 wxString
name = wxT(
"UNKNOWN" );
3879 if( !ii && company[ii] )
3887 else if( !ii && !company_name[ii].
empty() )
3889 name = company_name[ii];
3891 else if( ii && !
m_dist.empty() )
3896 auto [vendor_id, inserted] = unique_vendors.emplace(
3898 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3900 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3904 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3920 const std::map<std::string, UTF8>* aProperties )
3963 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3965 if( it->second ==
"inch" )
3972 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3973 m_sigfig = std::stoi( it->second );
3975 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3978 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3981 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3982 m_mpn = it->second.wx_str();
3984 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3985 m_mfg = it->second.wx_str();
3987 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3988 m_dist = it->second.wx_str();
3990 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3995 for(
char c =
'a'; c <=
'z'; ++c )
3998 for(
char c =
'A'; c <=
'Z'; ++c )
4001 for(
char c =
'0'; c <=
'9'; ++c )
4005 std::string specialChars =
"_\\-.+><";
4007 for(
char c : specialChars )
4036 double written_bytes = 0.0;
4037 double last_yield = 0.0;
4044 auto update_progress = [&](
size_t aBytes )
4046 written_bytes += aBytes;
4047 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
4052 if( last_yield + 0.01 < percent )
4054 last_yield = percent;
4068 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.
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.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
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