53#include <wx/numformatter.h>
54#include <wx/xml/xml.h>
134 std::vector<FOOTPRINT*> retval;
137 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
147 if( aParent->GetChildren() )
148 aNode->SetNext( aParent->GetChildren() );
150 aNode->SetNext(
nullptr );
152 aParent->SetChildren( aNode );
153 aNode->SetParent( aParent );
162 aNode->SetNext( aPrev->GetNext() );
163 aPrev->SetNext( aNode );
164 aNode->SetParent( aPrev->GetParent() );
185 check = check->GetParent();
198 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
213 aNode->SetParent( aParent );
218 aParent->AddChild( aNode );
230 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
244 str.Replace( wxT(
":" ), wxT(
"_" ) );
248 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
265 wxString key = aPrefix ? wxString( aPrefix ) + wxT(
":" ) + aStr : aStr;
275 wxString
name = base;
279 name = wxString::Format(
"%s_%d", base, suffix++ );
295 const char* aPrefix )
const
297 return genString( wxString::Format( wxS(
"%s_%s" ),
299 m_board->GetLayerName( aBottom ) ), aPrefix );
310 if(
name.empty() && fp )
314 if( fp->
Pads()[ii] == aPad )
322 name = wxString::Format(
"NPTH%zu", ii );
323 else if(
name.empty() )
324 name = wxString::Format(
"PAD%zu", ii );
335 [&](
const wxString& aName )
358 wxString baseName =
genString( ref,
"CMP" );
359 wxString
name = baseName;
362 while( !tryInsert(
name ) )
363 name = wxString::Format(
"%s_%d", baseName, suffix++ );
373 wxString str = wxString::FromCDouble( aVal, aSigFig == -1 ?
m_sigfig : aSigFig );
376 while( str.EndsWith( wxT(
"00" ) ) )
380 if( str == wxT(
"-0.0" ) )
405 aNode->AddAttribute( aName, aValue );
411 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
413 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
414 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
415 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
420 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
425 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
430 return xmlHeaderNode;
443 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
451 wxFileName fn(
m_board->GetFileName() );
458 contentNode->AddChild( color_node );
462 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
482 contentNode->AddChild( color_node );
491 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
566 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
570 wxString layer_name = item->GetLayerName();
571 int sub_layer_count = 1;
573 if( layer_name.empty() )
574 layer_name =
m_board->GetLayerName( item->GetBrdLayerId() );
576 layer_name =
genString( layer_name,
"LAYER" );
580 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
582 sub_layer_count = item->GetSublayersCount();
589 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
591 wxString sub_layer_name = layer_name;
594 sub_layer_name += wxString::Format(
"_%d", sub_idx );
596 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
602 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
604 wxXmlNode* color =
appendNode( entry_color,
"Color" );
606 wxString colorName = item->GetColor( sub_idx );
608 if( colorName.StartsWith( wxT(
"#" ) ) )
611 COLOR4D layer_color( colorName );
623 if( fab_color.GetName() == colorName )
625 addAttribute( color,
"r", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).r * 255 ) ) );
626 addAttribute( color,
"g", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).g * 255 ) ) );
627 addAttribute( color,
"b", wxString::Format(
"%d",
KiROUND( fab_color.GetColor( item->GetType() ).b * 255 ) ) );
647 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
653 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
654 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
661 wxCHECK_RET( aNode,
"aNode is null" );
666 wxXmlNode* entry_node =
nullptr;
670 size_t hash =
lineHash( aWidth, aDashType );
671 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
675 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
690 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
737 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
739 std::list<VECTOR2I> pts;
747 wxXmlNode* line_node =
nullptr;
754 addXY( line_node, pts.front(),
"startX",
"startY" );
755 addXY( line_node, pts.back(),
"endX",
"endY" );
759 line_node =
appendNode( text_node,
"Polyline" );
760 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
761 addXY( point_node, pts.front() );
763 auto iter = pts.begin();
765 for( ++iter; iter != pts.end(); ++iter )
767 wxXmlNode* step_node =
appendNode( line_node,
"PolyStepSegment" );
768 addXY( step_node, *iter );
783 if( aPt1 == pts.back() )
784 pts.push_back( aPt2 );
785 else if( aPt2 == pts.front() )
786 pts.push_front( aPt1 );
787 else if( aPt1 == pts.front() )
788 pts.push_front( aPt2 );
789 else if( aPt2 == pts.back() )
790 pts.push_back( aPt1 );
794 pts.push_back( aPt1 );
795 pts.push_back( aPt2 );
800 pts.push_back( aPt1 );
801 pts.push_back( aPt2 );
807 if( aPoly.PointCount() < 3 )
810 wxXmlNode* outline_node =
appendNode( text_node,
"Outline" );
811 wxXmlNode* poly_node =
appendNode( outline_node,
"Polygon" );
814 const std::vector<VECTOR2I>& polyPts = aPoly.CPoints();
815 wxXmlNode* point_node =
appendNode( poly_node,
"PolyBegin" );
816 addXY( point_node, polyPts.front() );
818 for(
size_t ii = 1; ii < polyPts.size(); ++ii )
820 wxXmlNode* poly_step_node =
822 addXY( poly_step_node, polyPts[ii] );
825 point_node =
appendNode( poly_node,
"PolyStepSegment" );
826 addXY( point_node, polyPts.front() );
837 if( text_node->GetChildren() ==
nullptr )
839 aContentNode->RemoveChild( text_node );
852 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
857 int maxError =
m_board->GetDesignSettings().m_MaxError;
877 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
878 circle_node->AddAttribute(
"diameter",
891 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
907 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
923 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
927 roundrect_node->AddAttribute(
"radius",
945 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
950 int shorterSide = std::min( pad_size.
x, pad_size.
y );
981 int dx = pad_size.
x / 2;
982 int dy = pad_size.
y / 2;
983 int ddx = trap_delta.
x / 2;
984 int ddy = trap_delta.
y / 2;
986 outline.
Append( -dx - ddy, dy + ddx );
987 outline.
Append( dx + ddy, dy - ddx );
988 outline.
Append( dx - ddy, -dy + ddx );
989 outline.
Append( -dx + ddy, -dy - ddx );
1014 if( expansion !=
VECTOR2I( 0, 0 ) )
1031 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
1046 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1063 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1071 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1072 addXY( begin_node, start );
1075 wxXmlNode* arc1_node =
appendNode( polyline_node,
"PolyStepCurve" );
1076 addXY( arc1_node, mid );
1081 wxXmlNode* arc2_node =
appendNode( polyline_node,
"PolyStepCurve" );
1082 addXY( arc2_node, start );
1094 int diameter = aShape.
GetRadius() * 2.0;
1101 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1103 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
1129 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1134 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1135 addXY( begin_node, corners[0] );
1137 for(
size_t i = 1; i < corners.size(); ++i )
1139 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1140 addXY( step_node, corners[i] );
1144 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1145 addXY( close_node, corners[0] );
1147 if( stroke_width > 0 )
1148 addLineDesc( polyline_node, stroke_width, dash,
true );
1158 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1164 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1181 width += stroke_width;
1182 height += stroke_width;
1210 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1211 const std::vector<VECTOR2I>& pts = outline.
CPoints();
1213 wxXmlNode* begin_node =
appendNode( polyline_node,
"PolyBegin" );
1214 addXY( begin_node, pts[0] );
1216 for(
size_t jj = 1; jj < pts.size(); ++jj )
1218 wxXmlNode* step_node =
appendNode( polyline_node,
"PolyStepSegment" );
1219 addXY( step_node, pts[jj] );
1223 if( pts.size() > 2 && pts.front() != pts.back() )
1225 wxXmlNode* close_node =
appendNode( polyline_node,
"PolyStepSegment" );
1226 addXY( close_node, pts[0] );
1229 if( stroke_width > 0 )
1230 addLineDesc( polyline_node, stroke_width, dash,
true );
1244 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1266 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1268 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1285 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1289 std::vector<VECTOR2I> points;
1292 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1293 addXY( point_node, points[0] );
1295 for(
size_t i = 1; i < points.size(); i++ )
1297 wxXmlNode* seg_node =
appendNode( polyline_node,
"PolyStepSegment" );
1298 addXY( seg_node, points[i] );
1312 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1314 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1330 if( !aInline && !
name.empty() )
1332 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1341 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1361 if( drill_size.
y > drill_size.
x )
1363 std::swap( drill_size.
x, drill_size.
y );
1364 rotation = ( rotation +
ANGLE_90 ).Normalize();
1370 wxXmlNode* xformNode =
appendNode( slotNode,
"Xform" );
1375 wxXmlNode* ovalNode =
appendNode( slotNode,
"Oval" );
1383 int maxError =
m_board->GetDesignSettings().m_MaxError;
1395 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1403 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1405 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1408 return logisticNode;
1419 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1421 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1423 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1424 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1425 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1428 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1431 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1433 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1434 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1457 m_refdes =
new std::vector<REFDES>();
1458 m_props =
new std::map<wxString, wxString>();
1469 wxString m_OEMDesignRef;
1473 wxString m_description;
1475 std::vector<REFDES>* m_refdes;
1476 std::map<wxString, wxString>*
m_props;
1479 std::set<std::unique_ptr<struct BOM_ENTRY>,
1480 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1481 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1482 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1483 const std::unique_ptr<struct BOM_ENTRY>& b )
1485 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1490 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1491 fp->SetParentGroup(
nullptr );
1492 fp->SetPosition( {0, 0} );
1493 fp->SetOrientation(
ANGLE_0 );
1496 if( fp->IsFlipped() )
1504 Report( wxString::Format(
_(
"Footprint %s not found in dictionary; BOM data may be incomplete." ),
1505 fp->GetFPID().GetLibItemName().wx_str() ),
1510 auto entry = std::make_unique<struct BOM_ENTRY>();
1516 entry->m_OEMDesignRef = it->second;
1520 Report( wxString::Format(
_(
"Component \"%s\" missing OEM reference; BOM entry will be skipped." ),
1521 fp->GetFPID().GetLibItemName().wx_str() ),
1525 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1527 entry->m_pads = fp->GetPadCount();
1531 const wxString variantName =
m_board ?
m_board->GetCurrentVariant() : wxString();
1533 if( entry->m_pads == 0 || fp_it->GetExcludedFromBOMForVariant( variantName ) )
1534 entry->m_type =
"DOCUMENT";
1536 entry->m_type =
"ELECTRICAL";
1541 if( descField && !descField->
GetShownText(
false ).IsEmpty() )
1542 entry->m_description = descField->
GetShownText(
false );
1544 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1547 ( *bom_iter )->m_count++;
1551 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1552 refdes.m_populate = !fp->GetDNPForVariant( variantName )
1553 && !fp->GetExcludedFromBOMForVariant( variantName );
1556 ( *bom_iter )->m_refdes->push_back( refdes );
1560 for(
PCB_FIELD* prop : fp->GetFields() )
1565 if( prop->IsMandatory() && !prop->IsValue() )
1568 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetShownText(
false ) );
1572 if( bom_entries.empty() )
1575 wxFileName fn(
m_board->GetFileName() );
1577 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1578 m_xml_root->InsertChild( bomNode, aEcadNode );
1581 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1584 if( bomRevision.IsEmpty() )
1585 bomRevision =
m_board->GetTitleBlock().GetRevision();
1587 if( bomRevision.IsEmpty() )
1588 bomRevision = wxS(
"1.0" );
1590 addAttribute( bomHeaderNode,
"revision", bomRevision );
1593 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1596 for(
const auto& entry : bom_entries )
1598 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1599 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1600 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1601 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1602 addAttribute( bomEntryNode,
"category", entry->m_type );
1604 if( !entry->m_description.IsEmpty() )
1605 addAttribute( bomEntryNode,
"description", entry->m_description );
1607 for(
const REFDES& refdes : *( entry->m_refdes ) )
1609 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1612 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1613 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1616 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1617 addAttribute( characteristicsNode,
"category", entry->m_type );
1619 for(
const auto& prop : *( entry->m_props ) )
1621 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1622 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1623 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1624 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1642 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1661 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1662 std::set<PCB_LAYER_ID> added_layers;
1664 for(
int i = 0; i < stackup.
GetCount(); i++ )
1668 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1672 if( ly_name.IsEmpty() )
1681 if( sublayer_id > 0 )
1682 ly_name += wxString::Format(
"_%d", sublayer_id );
1686 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1688 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1690 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1692 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1694 switch ( stackup_item->
GetType() )
1699 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1701 propertyNode =
appendNode( conductorNode,
"Property" );
1702 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1703 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1709 propertyNode =
appendNode( generalNode,
"Property" );
1710 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1712 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1713 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1714 propertyNode =
appendNode( dielectricNode,
"Property" );
1717 dielectricNode =
appendNode( specNode,
"Dielectric" );
1718 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1719 propertyNode =
appendNode( dielectricNode,
"Property" );
1726 propertyNode =
appendNode( generalNode,
"Property" );
1727 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1729 propertyNode =
appendNode( generalNode,
"Property" );
1730 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1736 propertyNode =
appendNode( generalNode,
"Property" );
1737 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1739 propertyNode =
appendNode( generalNode,
"Property" );
1740 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1744 if( stackup_item->
GetEpsilonR( sublayer_id ) > 1.0 )
1746 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1747 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1748 propertyNode =
appendNode( dielectricNode,
"Property" );
1755 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1756 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1757 propertyNode =
appendNode( dielectricNode,
"Property" );
1773 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1776 wxXmlNode* surfaceFinishNode =
appendNode( specNode,
"SurfaceFinish" );
1777 wxXmlNode* finishNode =
appendNode( surfaceFinishNode,
"Finish" );
1789 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1833 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1874 aLayer ==
F_Cu ?
"TOP"
1875 : aLayer ==
B_Cu ?
"BOTTOM"
1893 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1894 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1901 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1903 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1904 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1909 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1910 std::set<PCB_LAYER_ID> added_layers;
1913 for(
int i = 0; i < stackup.
GetCount(); i++ )
1917 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1922 if( hasCoating && layer_id ==
F_Cu && sublayer_id == 0 )
1924 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1925 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_TOP" );
1929 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1931 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1935 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1938 if( ly_name.IsEmpty() )
1947 if( sublayer_id > 0 )
1948 ly_name += wxString::Format(
"_%d", sublayer_id );
1952 wxString spec_name =
genString( ly_name,
"SPEC_LAYER" );
1953 ly_name =
genString( ly_name,
"LAYER" );
1955 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1959 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1961 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1967 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1968 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_BOTTOM" );
1972 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1974 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1989 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1990 std::set<PCB_LAYER_ID> added_layers;
1992 for(
int i = 0; i < stackup.
GetCount(); i++ )
1999 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
2001 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2004 if( ly_name.IsEmpty() )
2014 if( sublayer_id > 0 )
2015 ly_name += wxString::Format(
"_%d", sublayer_id );
2019 ly_name =
genString( ly_name,
"LAYER" );
2026 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
2028 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
2043 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
2052 added_layers.insert( layer );
2053 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2064 wxXmlNode* topCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2066 addAttribute( topCoatingNode,
"layerFunction",
"COATINGCOND" );
2068 addAttribute( topCoatingNode,
"polarity",
"POSITIVE" );
2070 wxXmlNode* botCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2071 addAttribute( botCoatingNode,
"name",
"COATING_BOTTOM" );
2072 addAttribute( botCoatingNode,
"layerFunction",
"COATINGCOND" );
2074 addAttribute( botCoatingNode,
"polarity",
"POSITIVE" );
2092 for(
PAD*
pad : fp->Pads() )
2094 if(
pad->HasDrilledHole() )
2096 else if(
pad->HasHole() )
2103 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2104 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2109 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2116 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2117 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2123 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2139 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
2141 if(
via->Padstack().IsFilled().value_or(
false ) )
2144 if(
via->Padstack().IsCapped().value_or(
false ) )
2149 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
2152 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
2155 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
2159 for(
auto& tuple : new_layers )
2165 bool add_node =
true;
2168 wxString layerFunction;
2171 switch( std::get<0>(layers) )
2175 layerFunction =
"COATINGNONCOND";
2179 layerFunction =
"HOLEFILL";
2183 layerFunction =
"COATINGNONCOND";
2187 layerFunction =
"HOLEFILL";
2191 layerFunction =
"COATINGCOND";
2199 if( add_node && !vec.empty() )
2201 wxXmlNode* node =
appendNode( aCadLayerNode,
"Layer" );
2215 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
2216 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
2218 if( first_external )
2220 if( second_external )
2227 if( second_external )
2233 wxXmlNode* spanNode =
appendNode( node,
"Span" );
2244 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
2245 wxFileName fn(
m_board->GetFileName() );
2251 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
2271 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2278 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
2285 addShape( padNode, *aPad, aLayer );
2289 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
2302 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2323 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
2330 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2345 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2346 padStackHoleNode->AddAttribute(
"name",
2347 wxString::Format(
"%s%d_%d",
2363 if( !
m_board->IsLayerEnabled( layer ) )
2366 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2368 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2376 addShape( padStackPadDefNode, shape );
2380 addShape( padStackPadDefNode, *aPad, layer );
2392 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2399 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2405 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2408 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2416 auto addPadShape{ [&](
PCB_LAYER_ID aLayer,
const PCB_VIA* aViaShape,
const wxString& aLayerRef,
2417 bool aDrill ) ->
void
2422 shape.
SetEnd( {
KiROUND( aViaShape->GetDrillValue() / 2.0 ), 0 } );
2424 shape.
SetEnd( {
KiROUND( aViaShape->GetWidth( aLayer ) / 2.0 ), 0 } );
2426 wxXmlNode* padStackPadDefNode =
2427 appendNode( padStackDefNode,
"PadstackPadDef" );
2428 addAttribute( padStackPadDefNode,
"layerRef", aLayerRef );
2429 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2432 addShape( padStackPadDefNode, shape );
2452 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2455 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2458 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2473 if( secondary.
size.
x <= 0 && secondary.
size.
y <= 0 )
2484 if( !layerHasRef( secondary.
start ) || !layerHasRef( secondary.
end ) )
2505 wxXmlNode* backdrillNode =
appendNode( specNode,
"Backdrill" );
2506 addAttribute( backdrillNode,
"startLayerRef", startLayer->second );
2507 addAttribute( backdrillNode,
"mustNotCutLayerRef", endLayer->second );
2511 if( stubLength < 0 )
2526 addAttribute( backdrillNode,
"postMachining", isPostMachined ? wxT(
"true" )
2537 wxString primarySpec = createSpec( primary, wxString::Format( wxT(
"BD_%dA" ), specIndex ) );
2539 wxString secondarySpec = createSpec( secondary, wxString::Format( wxT(
"BD_%dB" ), specIndex ) );
2541 if( primarySpec.IsEmpty() && secondarySpec.IsEmpty() )
2556 auto addRef = [&](
const wxString& aSpecName )
2558 if( aSpecName.IsEmpty() )
2561 wxXmlNode* specRefNode =
appendNode( aHoleNode,
"SpecRef" );
2566 addRef( it->second.first );
2567 addRef( it->second.second );
2582 wxXmlNode* specNode = it->second;
2604 wxXmlNode* polygonNode =
nullptr;
2612 polygonNode =
appendNode( aParentNode,
"Polygon" );
2613 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2615 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2616 addXY( polybeginNode, pts[0] );
2618 for(
size_t ii = 1; ii < pts.size(); ++ii )
2620 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2621 addXY( polyNode, pts[ii] );
2624 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2625 addXY( polyendNode, pts[0] );
2636 addLineDesc( polygonNode, aWidth, aDashType,
true );
2640 wxCHECK( aWidth == 0,
false );
2653 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2655 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2657 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2658 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2660 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2661 addXY( polybeginNode, hole[0] );
2663 for(
size_t jj = 1; jj < hole.size(); ++jj )
2665 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2666 addXY( polyNode, hole[jj] );
2669 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2670 addXY( polyendNode, hole[0] );
2683 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2700 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2703 if( !outlineNode->GetChildren() )
2705 aParentNode->RemoveChild( outlineNode );
2722 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2732 aParentNode->RemoveChild( contourNode );
2745 if( !
m_board->GetBoardPolygonOutlines( board_outline,
false ) )
2751 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2755 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2756 aStepNode->RemoveChild( profileNode );
2782 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2783 fp->SetParentGroup(
nullptr );
2784 fp->SetPosition( { 0, 0 } );
2785 fp->SetOrientation(
ANGLE_0 );
2790 bool wasFlipped = fp->IsFlipped();
2793 if( fp->IsFlipped() )
2798 fp->GetFPID().GetLibItemName().wx_str(),
2802 addAttribute( aContentNode,
"packageRef", iter->second );
2809 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2810 wxXmlNode* otherSideViewNode =
nullptr;
2816 if( fp->FindPadByNumber(
"1" ) )
2818 else if ( fp->FindPadByNumber(
"A1" ) )
2820 else if ( fp->FindPadByNumber(
"A" ) )
2822 else if ( fp->FindPadByNumber(
"a" ) )
2824 else if ( fp->FindPadByNumber(
"a1" ) )
2826 else if ( fp->FindPadByNumber(
"Anode" ) )
2828 else if ( fp->FindPadByNumber(
"ANODE" ) )
2835 PAD* pinOnePad = fp->FindPadByNumber(
"1" );
2838 pinOnePad = fp->FindPadByNumber(
"A1" );
2840 if( pinOnePad && fp->Pads().size() >= 2 )
2843 BOX2I fpBBox = fp->GetBoundingBox();
2853 const char* orientation =
"OTHER";
2855 if( onCenterX && onCenterY )
2856 orientation =
"CENTER";
2857 else if( onCenterX && pinPos.
y <
center.y )
2858 orientation =
"UPPER_CENTER";
2859 else if( onCenterX && pinPos.
y >
center.y )
2860 orientation =
"LOWER_CENTER";
2861 else if( onCenterY && pinPos.
x <
center.x )
2862 orientation =
"LEFT";
2863 else if( onCenterY && pinPos.
x >
center.x )
2864 orientation =
"RIGHT";
2866 orientation =
"UPPER_LEFT";
2868 orientation =
"UPPER_RIGHT";
2870 orientation =
"LOWER_LEFT";
2872 orientation =
"LOWER_RIGHT";
2874 addAttribute( packageNode,
"pinOneOrientation", orientation );
2878 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2879 addAttribute( packageNode,
"comment",
"Pin 1 orientation could not be determined" );
2885 : fp->GetCourtyard(
F_CrtYd );
2887 : fp->GetCourtyard(
B_CrtYd );
2904 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2910 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2914 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2916 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2941 elements[item->GetLayer()][is_abs].push_back( item );
2944 auto add_base_node =
2947 wxXmlNode* parent = packageNode;
2956 bool is_other_side = wasFlipped ? ( aLayer ==
F_SilkS || aLayer ==
F_Fab )
2961 if( !otherSideViewNode )
2962 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2964 parent = otherSideViewNode;
2970 nodeName =
"SilkScreen";
2971 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2972 nodeName =
"AssemblyDrawing";
2976 wxXmlNode* new_node =
appendNode( parent, nodeName );
2980 auto add_marking_node =
2981 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2983 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2985 return marking_node;
2988 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2989 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2993 if( elements.find( layer ) != elements.end() )
2995 if( elements[layer][
true].size() > 0 )
2996 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2997 else if( elements[layer][
false].size() > 0 )
2998 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
3002 for(
auto& [layer, map] : elements )
3004 wxXmlNode* layer_node = add_base_node( layer );
3005 wxXmlNode* marking_node = add_marking_node( layer_node );
3006 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
3007 bool update_bbox =
false;
3011 layer_nodes[layer] = layer_node;
3015 for(
auto& [is_abs, vec] : map )
3019 wxXmlNode* output_node =
nullptr;
3022 layer_bbox[layer].Merge( item->GetBoundingBox() );
3025 output_node = add_marking_node( layer_node );
3027 output_node = group_node;
3029 switch( item->Type() )
3035 if(
text->IsKnockout() )
3049 if(
text->IsBorderEnabled() )
3052 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
3054 text->GetBorderWidth() );
3077 if( group_node->GetChildren() ==
nullptr )
3079 marking_node->RemoveChild( group_node );
3080 layer_node->RemoveChild( marking_node );
3082 delete marking_node;
3086 for(
auto&[layer, bbox] : layer_bbox )
3088 if( bbox.GetWidth() > 0 )
3090 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
3093 std::vector<VECTOR2I> points( 4 );
3094 points[0] = bbox.GetPosition();
3095 points[2] = bbox.GetEnd();
3096 points[1].x = points[0].x;
3097 points[1].y = points[2].y;
3098 points[3].x = points[2].x;
3099 points[3].y = points[0].y;
3101 outline.
Append( points );
3107 std::map<wxString, wxXmlNode*> pin_nodes;
3109 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
3111 PAD*
pad = fp->Pads()[ii];
3113 wxXmlNode* pinNode =
nullptr;
3115 auto [ it, inserted ] = pin_nodes.emplace( pin_name,
nullptr );
3120 it->second = pinNode;
3125 genString( fp->GetReference(),
"CMP" ), pin_name );
3128 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
3129 else if(
pad->IsOnCopperLayer() )
3130 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
3132 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
3134 if(
pad->HasHole() )
3139 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
3141 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
3142 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
3144 if( fp->IsFlipped() )
3161 if( otherSideViewNode )
3162 packageNode->AddChild( otherSideViewNode );
3170 std::vector<wxXmlNode*> componentNodes;
3171 std::vector<wxXmlNode*> packageNodes;
3172 std::set<wxString> packageNames;
3174 bool generate_unique =
m_OEMRef.empty();
3178 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
3180 wxXmlNode* pkg =
addPackage( componentNode, fp );
3183 packageNodes.push_back( pkg );
3189 if( !generate_unique )
3192 if( field && !field->
GetText().empty() )
3198 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
3199 fp->GetFPID().GetLibItemName().wx_str(),
3204 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
3212 else if( fp->GetAttributes() &
FP_SMD )
3217 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
3219 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
3226 if( fp->IsFlipped() )
3230 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
3232 componentNodes.push_back( componentNode );
3241 for( wxXmlNode* pkg : packageNodes )
3242 aStepNode->AddChild( pkg );
3244 for( wxXmlNode* cmp : componentNodes )
3245 aStepNode->AddChild( cmp );
3253 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
3255 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
3257 for(
auto& [cmp,
pin] : pin_pair )
3259 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
3273 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
3277 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
3279 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
3280 [&layers, &elements](
PCB_TRACK* aTrack )
3282 if( aTrack->Type() == PCB_VIA_T )
3284 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
3286 for( PCB_LAYER_ID layer : layers )
3288 if( via->FlashLayer( layer ) )
3289 elements[layer][via->GetNetCode()].push_back( via );
3294 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
3298 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
3299 [ &elements ](
ZONE* zone )
3301 LSEQ zone_layers = zone->GetLayerSet().Seq();
3303 for( PCB_LAYER_ID layer : zone_layers )
3304 elements[layer][zone->GetNetCode()].push_back( zone );
3307 for(
BOARD_ITEM* item : m_board->Drawings() )
3310 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
3312 elements[item->GetLayer()][0].push_back( item );
3315 for(
FOOTPRINT* fp : m_board->Footprints() )
3317 for(
PCB_FIELD* field : fp->GetFields() )
3318 elements[field->GetLayer()][0].push_back( field );
3320 for(
BOARD_ITEM* item : fp->GraphicalItems() )
3321 elements[item->GetLayer()][0].push_back( item );
3323 for(
PAD*
pad : fp->Pads() )
3325 LSEQ pad_layers =
pad->GetLayerSet().Seq();
3329 if(
pad->FlashLayer( layer ) )
3330 elements[layer][
pad->GetNetCode()].push_back(
pad );
3357 if( m_progressReporter )
3358 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
3360 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
3361 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
3363 auto process_net = [&] (
int net )
3365 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
3370 std::stable_sort( vec.begin(), vec.end(),
3373 if( a->GetParentFootprint() == b->GetParentFootprint() )
3374 return a->Type() < b->Type();
3376 return a->GetParentFootprint() < b->GetParentFootprint();
3379 generateLayerSetNet( layerNode, layer, vec );
3384 if( m_progressReporter )
3386 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
3387 m_board->GetLayerName( layer ),
3388 net->GetNetname() ) );
3389 m_progressReporter->AdvanceProgress();
3392 process_net( net->GetNetCode() );
3395 if( layerNode->GetChildren() ==
nullptr )
3397 aStepNode->RemoveChild( layerNode );
3398 deleteNode( layerNode );
3410 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3411 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
3422 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
3427 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3430 if(
via->GetNetCode() > 0 )
3433 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3434 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3439 addXY( holeNode,
via->GetPosition() );
3449 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
3454 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3457 if(
pad->GetNetCode() > 0 )
3460 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3461 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3467 addXY( holeNode,
pad->GetPosition() );
3477 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3478 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
3482 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3484 if(
pad->GetNetCode() > 0 )
3487 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
3494 std::vector<BOARD_ITEM*>& aItems )
3496 auto it = aItems.begin();
3497 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
3498 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
3499 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
3501 bool has_via =
false;
3502 bool has_pad =
false;
3504 wxXmlNode* padSetNode =
nullptr;
3506 wxXmlNode* viaSetNode =
nullptr;
3508 wxXmlNode* teardropLayerSetNode =
nullptr;
3509 wxXmlNode* teardropFeatureSetNode =
nullptr;
3511 bool teardrop_warning =
false;
3516 if( item->GetNetCode() > 0 )
3526 shape.
SetStart( track->GetStart() );
3527 shape.
SetEnd( track->GetEnd() );
3528 shape.
SetWidth( track->GetWidth() );
3545 viaSetNode = layerSetNode;
3550 viaSetNode =
appendNode( layerSetNode,
"Set" );
3552 if( track->GetNetCode() > 0 )
3559 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
3566 wxXmlNode* zoneFeatureNode = specialNode;
3568 if( zone->IsTeardropArea() )
3572 if( !teardropFeatureSetNode )
3574 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
3575 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
3577 if( zone->GetNetCode() > 0 )
3580 genString( zone->GetNetname(),
"NET" ) );
3583 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3585 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3588 zoneFeatureNode = teardropFeatureSetNode;
3590 else if( !teardrop_warning )
3592 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3594 teardrop_warning =
true;
3601 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3604 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3606 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3610 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3612 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3623 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3626 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3628 bool link_to_component =
true;
3631 link_to_component =
false;
3633 if( link_to_component )
3636 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3645 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3647 if( shape->GetNetCode() > 0 )
3650 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3667 text_item =
static_cast<EDA_TEXT*
>( pcb_text );
3669 text_item =
static_cast<EDA_TEXT*
>( pcb_textbox );
3674 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3679 bool link_to_component = fp !=
nullptr;
3682 link_to_component =
false;
3684 if( link_to_component )
3687 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3688 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3690 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3692 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3698 addText( tempFeature, text_item,
text->GetFontMetrics() );
3716 padSetNode = layerSetNode;
3721 padSetNode =
appendNode( aLayerNode,
"Set" );
3723 if(
pad->GetNetCode() > 0 )
3738 switch( item->Type() )
3743 add_track(
static_cast<PCB_TRACK*
>( item ) );
3751 add_pad(
static_cast<PAD*
>( item ) );
3755 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3780 if( specialNode->GetChildren() ==
nullptr )
3782 featureSetNode->RemoveChild( specialNode );
3786 if( featureSetNode->GetChildren() ==
nullptr )
3788 layerSetNode->RemoveChild( featureSetNode );
3792 if( layerSetNode->GetChildren() ==
nullptr )
3794 aLayerNode->RemoveChild( layerSetNode );
3803 bool add_node =
true;
3809 switch( std::get<0>(layers) )
3838 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3842 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3856 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3858 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3882 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3886 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3889 std::set<wxString> unique_parts;
3890 std::map<wxString,wxString> unique_vendors;
3894 auto [ it, success ] = unique_parts.insert(
name );
3899 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3906 for (
int ii = 0; ii < 2; ++ii )
3912 if( mpn_name.empty() )
3915 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3919 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3922 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3924 wxString vendor_name = wxT(
"UNKNOWN" );
3927 if( !ii && company[ii] )
3935 else if( !ii && !company_name[ii].
empty() )
3937 vendor_name = company_name[ii];
3939 else if( ii && !
m_dist.empty() )
3944 auto [vendor_id, inserted] = unique_vendors.emplace(
3946 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3948 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3952 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3968 const std::map<std::string, UTF8>* aProperties )
4012 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
4014 if( it->second ==
"inch" )
4021 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
4022 m_sigfig = std::stoi( it->second );
4024 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
4027 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
4030 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
4031 m_mpn = it->second.wx_str();
4033 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
4034 m_mfg = it->second.wx_str();
4036 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
4037 m_dist = it->second.wx_str();
4039 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
4042 if(
auto it = aProperties->find(
"bomrev" ); it != aProperties->end() )
4047 for(
char c =
'a'; c <=
'z'; ++c )
4050 for(
char c =
'A'; c <=
'Z'; ++c )
4053 for(
char c =
'0'; c <=
'9'; ++c )
4057 std::string specialChars =
"_\\-.+><";
4059 for(
char c : specialChars )
4086 wxXmlNode* insertBefore =
nullptr;
4088 for( wxXmlNode* child =
m_contentNode->GetChildren(); child; child = child->GetNext() )
4090 if( child->GetName().StartsWith(
"Dictionary" ) )
4092 insertBefore = child;
4098 [&](
const wxString& aNodeName, wxXmlNode* aSection )
4103 wxXmlNode* ref =
new wxXmlNode( wxXML_ELEMENT_NODE, aNodeName );
4104 ref->AddAttribute(
"name", aSection->GetAttribute(
"name" ) );
4112 insertRef(
"BomRef", bom_node );
4113 insertRef(
"AvlRef", avl_node );
4122 double written_bytes = 0.0;
4123 double last_yield = 0.0;
4130 auto update_progress = [&](
size_t aBytes )
4132 written_bytes += aBytes;
4133 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
4138 if( last_yield + 0.01 < percent )
4140 last_yield = percent;
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 size_type GetWidth() const
constexpr const Vec GetCenter() const
constexpr size_type GetHeight() 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.
wxString AsString() const
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.
wxXmlNode * m_contentNode
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
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)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
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