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" );
1775 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1778 wxXmlNode* surfaceFinishNode =
appendNode( specNode,
"SurfaceFinish" );
1790 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1834 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1875 aLayer ==
F_Cu ?
"TOP"
1876 : aLayer ==
B_Cu ?
"BOTTOM"
1895 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1896 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1903 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1905 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1906 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1911 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1912 std::set<PCB_LAYER_ID> added_layers;
1915 for(
int i = 0; i < stackup.
GetCount(); i++ )
1919 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1924 if( hasCoating && layer_id ==
F_Cu && sublayer_id == 0 )
1926 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1927 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_TOP" );
1931 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1933 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1937 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1940 if( ly_name.IsEmpty() )
1949 if( sublayer_id > 0 )
1950 ly_name += wxString::Format(
"_%d", sublayer_id );
1954 wxString spec_name =
genString( ly_name,
"SPEC_LAYER" );
1955 ly_name =
genString( ly_name,
"LAYER" );
1957 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1961 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1963 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1969 wxXmlNode* coatingLayer =
appendNode( stackupGroup,
"StackupLayer" );
1970 addAttribute( coatingLayer,
"layerOrGroupRef",
"COATING_BOTTOM" );
1974 addAttribute( coatingLayer,
"sequence", wxString::Format(
"%d", sequence++ ) );
1976 wxXmlNode* specRefNode =
appendNode( coatingLayer,
"SpecRef" );
1991 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1992 std::set<PCB_LAYER_ID> added_layers;
1994 for(
int i = 0; i < stackup.
GetCount(); i++ )
2001 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
2003 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2006 if( ly_name.IsEmpty() )
2016 if( sublayer_id > 0 )
2017 ly_name += wxString::Format(
"_%d", sublayer_id );
2021 ly_name =
genString( ly_name,
"LAYER" );
2028 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
2030 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
2045 LSEQ layer_seq =
m_board->GetEnabledLayers().Seq();
2054 added_layers.insert( layer );
2055 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
2068 wxXmlNode* topCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2070 addAttribute( topCoatingNode,
"layerFunction",
"COATINGCOND" );
2072 addAttribute( topCoatingNode,
"polarity",
"POSITIVE" );
2074 wxXmlNode* botCoatingNode =
appendNode( aCadLayerNode,
"Layer" );
2075 addAttribute( botCoatingNode,
"name",
"COATING_BOTTOM" );
2076 addAttribute( botCoatingNode,
"layerFunction",
"COATINGCOND" );
2078 addAttribute( botCoatingNode,
"polarity",
"POSITIVE" );
2097 for(
PAD*
pad : fp->Pads() )
2099 if(
pad->HasDrilledHole() )
2101 else if(
pad->HasHole() )
2108 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2109 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2114 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2121 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
2122 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2128 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
2144 std::vector<std::tuple<auxLayerType, PCB_LAYER_ID, PCB_LAYER_ID>> new_layers;
2146 if(
via->Padstack().IsFilled().value_or(
false ) )
2149 if(
via->Padstack().IsCapped().value_or(
false ) )
2154 if(
via->Padstack().IsPlugged( layer ).value_or(
false ) )
2157 if(
via->Padstack().IsCovered( layer ).value_or(
false ) )
2160 if(
via->Padstack().IsTented( layer ).value_or(
false ) )
2164 for(
auto& tuple : new_layers )
2170 bool add_node =
true;
2173 wxString layerFunction;
2176 switch( std::get<0>(layers) )
2180 layerFunction =
"COATINGNONCOND";
2184 layerFunction =
"HOLEFILL";
2188 layerFunction =
"COATINGNONCOND";
2192 layerFunction =
"HOLEFILL";
2196 layerFunction =
"COATINGCOND";
2204 if( add_node && !vec.empty() )
2206 wxXmlNode* node =
appendNode( aCadLayerNode,
"Layer" );
2220 const bool first_external = std::get<1>( layers ) ==
F_Cu || std::get<1>( layers ) ==
B_Cu;
2221 const bool second_external = std::get<2>( layers ) ==
F_Cu || std::get<2>( layers ) ==
B_Cu;
2223 if( first_external )
2225 if( second_external )
2232 if( second_external )
2238 wxXmlNode* spanNode =
appendNode( node,
"Span" );
2249 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
2250 wxFileName fn(
m_board->GetFileName() );
2256 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
2276 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2283 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
2290 addShape( padNode, *aPad, aLayer );
2294 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
2307 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
2328 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
2335 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2350 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2351 padStackHoleNode->AddAttribute(
"name",
2352 wxString::Format(
"%s%d_%d",
2368 if( !
m_board->IsLayerEnabled( layer ) )
2371 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
2373 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2381 addShape( padStackPadDefNode, shape );
2385 addShape( padStackPadDefNode, *aPad, layer );
2397 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
2404 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
2410 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
2413 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
2421 auto addPadShape{ [&](
PCB_LAYER_ID aLayer,
const PCB_VIA* aViaShape,
const wxString& aLayerRef,
2422 bool aDrill ) ->
void
2427 shape.
SetEnd( {
KiROUND( aViaShape->GetDrillValue() / 2.0 ), 0 } );
2429 shape.
SetEnd( {
KiROUND( aViaShape->GetWidth( aLayer ) / 2.0 ), 0 } );
2431 wxXmlNode* padStackPadDefNode =
2432 appendNode( padStackDefNode,
"PadstackPadDef" );
2433 addAttribute( padStackPadDefNode,
"layerRef", aLayerRef );
2434 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
2437 addShape( padStackPadDefNode, shape );
2457 addPadShape( layer, aVia,
genLayerString( layer,
"PLUGGING" ),
true );
2460 addPadShape( layer, aVia,
genLayerString( layer,
"COVERING" ),
false );
2463 addPadShape( layer, aVia,
genLayerString( layer,
"TENTING" ),
false );
2478 if( secondary.
size.
x <= 0 && secondary.
size.
y <= 0 )
2489 if( !layerHasRef( secondary.
start ) || !layerHasRef( secondary.
end ) )
2510 wxXmlNode* backdrillNode =
appendNode( specNode,
"Backdrill" );
2511 addAttribute( backdrillNode,
"startLayerRef", startLayer->second );
2512 addAttribute( backdrillNode,
"mustNotCutLayerRef", endLayer->second );
2516 if( stubLength < 0 )
2531 addAttribute( backdrillNode,
"postMachining", isPostMachined ? wxT(
"true" )
2542 wxString primarySpec = createSpec( primary, wxString::Format( wxT(
"BD_%dA" ), specIndex ) );
2544 wxString secondarySpec = createSpec( secondary, wxString::Format( wxT(
"BD_%dB" ), specIndex ) );
2546 if( primarySpec.IsEmpty() && secondarySpec.IsEmpty() )
2561 auto addRef = [&](
const wxString& aSpecName )
2563 if( aSpecName.IsEmpty() )
2566 wxXmlNode* specRefNode =
appendNode( aHoleNode,
"SpecRef" );
2571 addRef( it->second.first );
2572 addRef( it->second.second );
2587 wxXmlNode* specNode = it->second;
2609 wxXmlNode* polygonNode =
nullptr;
2617 polygonNode =
appendNode( aParentNode,
"Polygon" );
2618 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
2620 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
2621 addXY( polybeginNode, pts[0] );
2623 for(
size_t ii = 1; ii < pts.size(); ++ii )
2625 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
2626 addXY( polyNode, pts[ii] );
2629 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
2630 addXY( polyendNode, pts[0] );
2641 addLineDesc( polygonNode, aWidth, aDashType,
true );
2645 wxCHECK( aWidth == 0,
false );
2658 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2660 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2662 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2663 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2665 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2666 addXY( polybeginNode, hole[0] );
2668 for(
size_t jj = 1; jj < hole.size(); ++jj )
2670 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2671 addXY( polyNode, hole[jj] );
2674 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2675 addXY( polyendNode, hole[0] );
2688 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2705 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2708 if( !outlineNode->GetChildren() )
2710 aParentNode->RemoveChild( outlineNode );
2727 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2737 aParentNode->RemoveChild( contourNode );
2750 if( !
m_board->GetBoardPolygonOutlines( board_outline,
false ) )
2756 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2760 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2761 aStepNode->RemoveChild( profileNode );
2787 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2788 fp->SetParentGroup(
nullptr );
2789 fp->SetPosition( { 0, 0 } );
2790 fp->SetOrientation(
ANGLE_0 );
2795 bool wasFlipped = fp->IsFlipped();
2798 if( fp->IsFlipped() )
2803 fp->GetFPID().GetLibItemName().wx_str(),
2807 addAttribute( aContentNode,
"packageRef", iter->second );
2814 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2815 wxXmlNode* otherSideViewNode =
nullptr;
2821 if( fp->FindPadByNumber(
"1" ) )
2823 else if ( fp->FindPadByNumber(
"A1" ) )
2825 else if ( fp->FindPadByNumber(
"A" ) )
2827 else if ( fp->FindPadByNumber(
"a" ) )
2829 else if ( fp->FindPadByNumber(
"a1" ) )
2831 else if ( fp->FindPadByNumber(
"Anode" ) )
2833 else if ( fp->FindPadByNumber(
"ANODE" ) )
2840 PAD* pinOnePad = fp->FindPadByNumber(
"1" );
2843 pinOnePad = fp->FindPadByNumber(
"A1" );
2845 if( pinOnePad && fp->Pads().size() >= 2 )
2848 BOX2I fpBBox = fp->GetBoundingBox();
2858 const char* orientation =
"OTHER";
2860 if( onCenterX && onCenterY )
2861 orientation =
"CENTER";
2862 else if( onCenterX && pinPos.
y <
center.y )
2863 orientation =
"UPPER_CENTER";
2864 else if( onCenterX && pinPos.
y >
center.y )
2865 orientation =
"LOWER_CENTER";
2866 else if( onCenterY && pinPos.
x <
center.x )
2867 orientation =
"LEFT";
2868 else if( onCenterY && pinPos.
x >
center.x )
2869 orientation =
"RIGHT";
2871 orientation =
"UPPER_LEFT";
2873 orientation =
"UPPER_RIGHT";
2875 orientation =
"LOWER_LEFT";
2877 orientation =
"LOWER_RIGHT";
2879 addAttribute( packageNode,
"pinOneOrientation", orientation );
2883 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2884 addAttribute( packageNode,
"comment",
"Pin 1 orientation could not be determined" );
2890 : fp->GetCourtyard(
F_CrtYd );
2892 : fp->GetCourtyard(
B_CrtYd );
2909 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2915 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2919 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2921 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2946 elements[item->GetLayer()][is_abs].push_back( item );
2949 auto add_base_node =
2952 wxXmlNode* parent = packageNode;
2961 bool is_other_side = wasFlipped ? ( aLayer ==
F_SilkS || aLayer ==
F_Fab )
2966 if( !otherSideViewNode )
2967 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2969 parent = otherSideViewNode;
2975 nodeName =
"SilkScreen";
2976 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2977 nodeName =
"AssemblyDrawing";
2981 wxXmlNode* new_node =
appendNode( parent, nodeName );
2985 auto add_marking_node =
2986 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2988 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2990 return marking_node;
2993 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2994 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2998 if( elements.find( layer ) != elements.end() )
3000 if( elements[layer][
true].size() > 0 )
3001 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
3002 else if( elements[layer][
false].size() > 0 )
3003 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
3007 for(
auto& [layer, map] : elements )
3009 wxXmlNode* layer_node = add_base_node( layer );
3010 wxXmlNode* marking_node = add_marking_node( layer_node );
3011 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
3012 bool update_bbox =
false;
3016 layer_nodes[layer] = layer_node;
3020 for(
auto& [is_abs, vec] : map )
3024 wxXmlNode* output_node =
nullptr;
3027 layer_bbox[layer].Merge( item->GetBoundingBox() );
3030 output_node = add_marking_node( layer_node );
3032 output_node = group_node;
3034 switch( item->Type() )
3040 if(
text->IsKnockout() )
3054 if(
text->IsBorderEnabled() )
3057 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
3059 text->GetBorderWidth() );
3082 if( group_node->GetChildren() ==
nullptr )
3084 marking_node->RemoveChild( group_node );
3085 layer_node->RemoveChild( marking_node );
3087 delete marking_node;
3091 for(
auto&[layer, bbox] : layer_bbox )
3093 if( bbox.GetWidth() > 0 )
3095 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
3098 std::vector<VECTOR2I> points( 4 );
3099 points[0] = bbox.GetPosition();
3100 points[2] = bbox.GetEnd();
3101 points[1].x = points[0].x;
3102 points[1].y = points[2].y;
3103 points[3].x = points[2].x;
3104 points[3].y = points[0].y;
3106 outline.
Append( points );
3112 std::map<wxString, wxXmlNode*> pin_nodes;
3114 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
3116 PAD*
pad = fp->Pads()[ii];
3118 wxXmlNode* pinNode =
nullptr;
3120 auto [ it, inserted ] = pin_nodes.emplace( pin_name,
nullptr );
3125 it->second = pinNode;
3130 genString( fp->GetReference(),
"CMP" ), pin_name );
3133 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
3134 else if(
pad->IsOnCopperLayer() )
3135 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
3137 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
3139 if(
pad->HasHole() )
3144 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
3146 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
3147 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
3149 if( fp->IsFlipped() )
3166 if( otherSideViewNode )
3167 packageNode->AddChild( otherSideViewNode );
3175 std::vector<wxXmlNode*> componentNodes;
3176 std::vector<wxXmlNode*> packageNodes;
3177 std::set<wxString> packageNames;
3179 bool generate_unique =
m_OEMRef.empty();
3183 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
3185 wxXmlNode* pkg =
addPackage( componentNode, fp );
3188 packageNodes.push_back( pkg );
3194 if( !generate_unique )
3197 if( field && !field->
GetText().empty() )
3203 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
3204 fp->GetFPID().GetLibItemName().wx_str(),
3209 Report(
_(
"Duplicate footprint pointers encountered; IPC-2581 output may be incorrect." ),
3217 else if( fp->GetAttributes() &
FP_SMD )
3222 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
3224 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
3231 if( fp->IsFlipped() )
3235 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
3237 componentNodes.push_back( componentNode );
3246 for( wxXmlNode* pkg : packageNodes )
3247 aStepNode->AddChild( pkg );
3249 for( wxXmlNode* cmp : componentNodes )
3250 aStepNode->AddChild( cmp );
3258 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
3260 genString(
m_board->GetNetInfo().GetNetItem( net )->GetNetname(),
"NET" ) ) ;
3262 for(
auto& [cmp,
pin] : pin_pair )
3264 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
3278 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
3282 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
3284 std::for_each(
m_board->Tracks().begin(),
m_board->Tracks().end(),
3285 [&layers, &elements](
PCB_TRACK* aTrack )
3287 if( aTrack->Type() == PCB_VIA_T )
3289 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
3291 for( PCB_LAYER_ID layer : layers )
3293 if( via->FlashLayer( layer ) )
3294 elements[layer][via->GetNetCode()].push_back( via );
3299 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
3303 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
3304 [ &elements ](
ZONE* zone )
3306 LSEQ zone_layers = zone->GetLayerSet().Seq();
3308 for( PCB_LAYER_ID layer : zone_layers )
3309 elements[layer][zone->GetNetCode()].push_back( zone );
3312 for(
BOARD_ITEM* item : m_board->Drawings() )
3315 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
3317 elements[item->GetLayer()][0].push_back( item );
3320 for(
FOOTPRINT* fp : m_board->Footprints() )
3322 for(
PCB_FIELD* field : fp->GetFields() )
3323 elements[field->GetLayer()][0].push_back( field );
3325 for(
BOARD_ITEM* item : fp->GraphicalItems() )
3326 elements[item->GetLayer()][0].push_back( item );
3328 for(
PAD*
pad : fp->Pads() )
3330 LSEQ pad_layers =
pad->GetLayerSet().Seq();
3334 if(
pad->FlashLayer( layer ) )
3335 elements[layer][
pad->GetNetCode()].push_back(
pad );
3362 if( m_progressReporter )
3363 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
3365 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
3366 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
3368 auto process_net = [&] (
int net )
3370 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
3375 std::stable_sort( vec.begin(), vec.end(),
3378 if( a->GetParentFootprint() == b->GetParentFootprint() )
3379 return a->Type() < b->Type();
3381 return a->GetParentFootprint() < b->GetParentFootprint();
3384 generateLayerSetNet( layerNode, layer, vec );
3389 if( m_progressReporter )
3391 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
3392 m_board->GetLayerName( layer ),
3393 net->GetNetname() ) );
3394 m_progressReporter->AdvanceProgress();
3397 process_net( net->GetNetCode() );
3400 if( layerNode->GetChildren() ==
nullptr )
3402 aStepNode->RemoveChild( layerNode );
3403 deleteNode( layerNode );
3415 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3416 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
3427 Report(
_(
"Via uses unsupported padstack; omitted from drill data." ),
3432 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3435 if(
via->GetNetCode() > 0 )
3438 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3439 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3444 addXY( holeNode,
via->GetPosition() );
3454 Report(
_(
"Pad uses unsupported padstack; hole was omitted from drill data." ),
3459 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3462 if(
pad->GetNetCode() > 0 )
3465 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
3466 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
3472 addXY( holeNode,
pad->GetPosition() );
3482 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
3483 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
3487 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
3489 if(
pad->GetNetCode() > 0 )
3492 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
3499 std::vector<BOARD_ITEM*>& aItems )
3501 auto it = aItems.begin();
3502 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
3503 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
3504 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
3506 bool has_via =
false;
3507 bool has_pad =
false;
3509 wxXmlNode* padSetNode =
nullptr;
3511 wxXmlNode* viaSetNode =
nullptr;
3513 wxXmlNode* teardropLayerSetNode =
nullptr;
3514 wxXmlNode* teardropFeatureSetNode =
nullptr;
3516 bool teardrop_warning =
false;
3521 if( item->GetNetCode() > 0 )
3531 shape.
SetStart( track->GetStart() );
3532 shape.
SetEnd( track->GetEnd() );
3533 shape.
SetWidth( track->GetWidth() );
3550 viaSetNode = layerSetNode;
3555 viaSetNode =
appendNode( layerSetNode,
"Set" );
3557 if( track->GetNetCode() > 0 )
3564 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
3571 wxXmlNode* zoneFeatureNode = specialNode;
3573 if( zone->IsTeardropArea() )
3577 if( !teardropFeatureSetNode )
3579 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
3580 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
3582 if( zone->GetNetCode() > 0 )
3585 genString( zone->GetNetname(),
"NET" ) );
3588 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
3590 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
3593 zoneFeatureNode = teardropFeatureSetNode;
3595 else if( !teardrop_warning )
3597 Report(
_(
"Teardrops are not supported in IPC-2581 revision B; they were exported as zones." ),
3599 teardrop_warning =
true;
3606 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3609 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
3611 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
3615 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
3617 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
3628 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3631 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
3633 bool link_to_component =
true;
3636 link_to_component =
false;
3638 if( link_to_component )
3641 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3650 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3652 if( shape->GetNetCode() > 0 )
3655 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3672 text_item =
static_cast<EDA_TEXT*
>( pcb_text );
3674 text_item =
static_cast<EDA_TEXT*
>( pcb_textbox );
3679 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
3684 bool link_to_component = fp !=
nullptr;
3687 link_to_component =
false;
3689 if( link_to_component )
3692 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
3693 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
3695 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
3697 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
3703 addText( tempFeature, text_item,
text->GetFontMetrics() );
3721 padSetNode = layerSetNode;
3726 padSetNode =
appendNode( aLayerNode,
"Set" );
3728 if(
pad->GetNetCode() > 0 )
3743 switch( item->Type() )
3748 add_track(
static_cast<PCB_TRACK*
>( item ) );
3756 add_pad(
static_cast<PAD*
>( item ) );
3760 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
3785 if( specialNode->GetChildren() ==
nullptr )
3787 featureSetNode->RemoveChild( specialNode );
3791 if( featureSetNode->GetChildren() ==
nullptr )
3793 layerSetNode->RemoveChild( featureSetNode );
3797 if( layerSetNode->GetChildren() ==
nullptr )
3799 aLayerNode->RemoveChild( layerSetNode );
3808 bool add_node =
true;
3814 switch( std::get<0>(layers) )
3843 wxXmlNode* layerNode =
appendNode( aStepNode,
"LayerFeature" );
3847 layerNode->AddAttribute(
"layerRef",
genLayersString( std::get<1>( layers ),
3861 shape.
SetEnd( {
KiROUND(
via->GetWidth( std::get<1>( layers ) ) / 2.0 ), 0 } );
3863 wxXmlNode* padNode =
appendNode( layerNode,
"Pad" );
3894 std::set<wxString> unique_parts;
3895 std::map<wxString,wxString> unique_vendors;
3899 auto [ it, success ] = unique_parts.insert(
name );
3904 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3911 for (
int ii = 0; ii < 2; ++ii )
3917 if( mpn_name.empty() )
3920 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3924 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3927 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3929 wxString vendor_name = wxT(
"UNKNOWN" );
3932 if( !ii && company[ii] )
3940 else if( !ii && !company_name[ii].
empty() )
3942 vendor_name = company_name[ii];
3944 else if( ii && !
m_dist.empty() )
3949 auto [vendor_id, inserted] = unique_vendors.emplace(
3951 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3953 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3957 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3973 const std::map<std::string, UTF8>* aProperties )
4017 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
4019 if( it->second ==
"inch" )
4026 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
4027 m_sigfig = std::stoi( it->second );
4029 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
4032 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
4035 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
4036 m_mpn = it->second.wx_str();
4038 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
4039 m_mfg = it->second.wx_str();
4041 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
4042 m_dist = it->second.wx_str();
4044 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
4047 if(
auto it = aProperties->find(
"bomrev" ); it != aProperties->end() )
4052 for(
char c =
'a'; c <=
'z'; ++c )
4055 for(
char c =
'A'; c <=
'Z'; ++c )
4058 for(
char c =
'0'; c <=
'9'; ++c )
4062 std::string specialChars =
"_\\-.+><";
4064 for(
char c : specialChars )
4091 wxXmlNode* insertBefore =
nullptr;
4093 for( wxXmlNode* child =
m_contentNode->GetChildren(); child; child = child->GetNext() )
4095 if( child->GetName().StartsWith(
"Dictionary" ) )
4097 insertBefore = child;
4103 [&](
const wxString& aNodeName, wxXmlNode* aSection )
4108 wxXmlNode* ref =
new wxXmlNode( wxXML_ELEMENT_NODE, aNodeName );
4109 ref->AddAttribute(
"name", aSection->GetAttribute(
"name" ) );
4117 insertRef(
"BomRef", bom_node );
4118 insertRef(
"AvlRef", avl_node );
4127 double written_bytes = 0.0;
4128 double last_yield = 0.0;
4135 auto update_progress = [&](
size_t aBytes )
4137 written_bytes += aBytes;
4138 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
4143 if( last_yield + 0.01 < percent )
4145 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".
std::vector< std::string > header
@ 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