47#include <wx/numformatter.h>
48#include <wx/xml/xml.h>
76 std::vector<FOOTPRINT*> retval;
79 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
89 if( aParent->GetChildren() )
90 aNode->SetNext( aParent->GetChildren() );
92 aNode->SetNext(
nullptr );
94 aParent->SetChildren( aNode );
95 aNode->SetParent( aParent );
104 aNode->SetNext( aPrev->GetNext() );
105 aPrev->SetNext( aNode );
106 aNode->SetParent( aPrev->GetParent() );
115 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
127 static wxXmlNode* lastNode =
nullptr;
129 if( lastNode && lastNode->GetParent() == aParent && lastNode->GetNext() ==
nullptr )
131 aNode->SetParent( aParent );
132 lastNode->SetNext( aNode );
136 aParent->AddChild( aNode );
148 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
162 str.Replace( wxT(
":" ), wxT(
"_" ) );
165 str.Prepend( wxString( aPrefix ) + wxT(
":" ) );
167 str.Prepend( wxT(
"KI:" ) );
172 str = wxString::Format(
"%s_", aPrefix );
174 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
194 const char* aPrefix )
const
196 return genString( wxString::Format( wxS(
"%s_%s" ),
209 if(
name.empty() && fp )
213 if( fp->
Pads()[ii] == aPad )
221 name = wxString::Format(
"NPTH%zu", ii );
222 else if(
name.empty() )
223 name = wxString::Format(
"PAD%zu", ii );
232 [&](
const wxString& aName )
251 wxString
name = baseName;
254 while( !tryInsert(
name ) )
255 name = wxString::Format(
"%s_%d", baseName, suffix++ );
265 wxString str = wxString::FromCDouble( aVal,
m_sigfig );
268 while( str.EndsWith( wxT(
"00" ) ) )
272 if( str == wxT(
"-0.0" ) )
297 aNode->AddAttribute( aName, aValue );
303 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
305 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
306 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
307 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
312 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
317 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
322 return xmlHeaderNode;
334 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
349 contentNode->AddChild( color_node );
353 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
373 contentNode->AddChild( color_node );
382 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
410 case SHAPE_T::RECTANGLE:
415 case SHAPE_T::CIRCLE:
421 case SHAPE_T::BEZIER:
422 case SHAPE_T::SEGMENT:
427 case SHAPE_T::UNDEFINED:
457 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
461 wxString layer_name = item->GetLayerName();
462 int sub_layer_count = 1;
464 if( layer_name.empty() )
467 layer_name =
genString( layer_name,
"LAYER" );
471 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
473 sub_layer_count = item->GetSublayersCount();
480 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
482 wxString sub_layer_name = layer_name;
485 sub_layer_name += wxString::Format(
"_%d", sub_idx );
487 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
493 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
497 wxString colorName = item->GetColor( sub_idx );
499 if( colorName.StartsWith( wxT(
"#" ) ) )
502 COLOR4D layer_color( colorName );
514 if( fab_color.GetName() == colorName )
532 if( aFill == FILL_T::FILLED_SHAPE )
538 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
544 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
545 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
552 wxCHECK_RET( aNode,
"aNode is null" );
557 wxXmlNode* entry_node =
nullptr;
561 size_t hash =
lineHash( aWidth, aDashType );
562 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
566 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
581 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
587 case LINE_STYLE::DOT:
590 case LINE_STYLE::DASH:
593 case LINE_STYLE::DASHDOT:
596 case LINE_STYLE::DASHDOTDOT:
631 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
636 std::list<VECTOR2I> pts;
644 wxXmlNode* line_node =
nullptr;
651 addXY( line_node, pts.front(),
"startX",
"startY" );
652 addXY( line_node, pts.back(),
"endX",
"endY" );
656 line_node =
appendNode( text_node,
"Polyline" );
657 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
658 addXY( point_node, pts.front() );
660 auto iter = pts.begin();
662 for( ++iter; iter != pts.end(); ++iter )
664 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
665 addXY( point_node, *iter );
680 if( aPt1 == pts.back() )
681 pts.push_back( aPt2 );
682 else if( aPt2 == pts.front() )
683 pts.push_front( aPt1 );
684 else if( aPt1 == pts.front() )
685 pts.push_front( aPt2 );
686 else if( aPt2 == pts.back() )
687 pts.push_back( aPt1 );
691 pts.push_back( aPt1 );
692 pts.push_back( aPt2 );
697 pts.push_back( aPt1 );
698 pts.push_back( aPt2 );
704 if( aPoly.PointCount() < 3 )
707 wxXmlNode* outline_node = appendNode( text_node,
"Outline" );
708 wxXmlNode* poly_node = appendNode( outline_node,
"Polygon" );
711 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
712 wxXmlNode* point_node = appendNode( poly_node,
"PolyBegin" );
713 addXY( point_node, pts.front() );
715 for(
size_t ii = 1; ii < pts.size(); ++ii )
717 wxXmlNode* point_node =
718 appendNode( poly_node,
"PolyStepSegment" );
719 addXY( point_node, pts[ii] );
722 point_node = appendNode( poly_node,
"PolyStepSegment" );
723 addXY( point_node, pts.front() );
728 font->Draw( &callback_gal, aText->GetShownText(
true ), aText->GetTextPos(), attrs,
734 if( text_node->GetChildren() == nullptr )
736 aContentNode->RemoveChild( text_node );
749 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
766 case PAD_SHAPE::CIRCLE:
774 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
775 circle_node->AddAttribute(
"diameter",
780 case PAD_SHAPE::RECTANGLE:
788 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
796 case PAD_SHAPE::OVAL:
804 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
812 case PAD_SHAPE::ROUNDRECT:
820 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
824 roundrect_node->AddAttribute(
"radius",
834 case PAD_SHAPE::CHAMFERED_RECT:
842 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
847 int shorterSide = std::min( pad_size.
x, pad_size.
y );
866 case PAD_SHAPE::TRAPEZOID:
878 int dx = pad_size.
x / 2;
879 int dy = pad_size.
y / 2;
880 int ddx = trap_delta.
x / 2;
881 int ddy = trap_delta.
y / 2;
883 outline.
Append( -dx - ddy, dy + ddx );
884 outline.
Append( dx + ddy, dy - ddx );
885 outline.
Append( dx - ddy, -dy + ddx );
886 outline.
Append( -dx + ddy, -dy - ddx );
900 case PAD_SHAPE::CUSTOM:
914 CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
922 wxLogError(
"Unknown pad type" );
929 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
943 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
950 case SHAPE_T::CIRCLE:
961 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
963 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
981 case SHAPE_T::RECTANGLE:
988 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
995 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1012 width += stroke_width;
1013 height += stroke_width;
1035 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1044 addContourNode( special_node, poly_set, ii, FILL_T::FILLED_SHAPE, 0,
1045 LINE_STYLE::SOLID );
1057 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1059 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1074 case SHAPE_T::BEZIER:
1076 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1080 std::vector<VECTOR2I> points;
1083 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1084 addXY( point_node, points[0] );
1086 for(
size_t i = 1; i < points.size(); i++ )
1088 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1089 addXY( point_node, points[i] );
1101 case SHAPE_T::SEGMENT:
1103 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1105 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1116 case SHAPE_T::UNDEFINED:
1122 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1131 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1152 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1160 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1162 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1165 return logisticNode;
1176 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1178 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1180 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1181 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1182 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1185 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1188 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1190 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1191 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1214 m_refdes =
new std::vector<REFDES>();
1215 m_props =
new std::map<wxString, wxString>();
1226 wxString m_OEMDesignRef;
1230 std::vector<REFDES>* m_refdes;
1231 std::map<wxString, wxString>* m_props;
1234 std::set<std::unique_ptr<struct BOM_ENTRY>,
1235 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1236 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1237 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1238 const std::unique_ptr<struct BOM_ENTRY>& b )
1240 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1245 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1246 fp->SetParentGroup(
nullptr );
1247 fp->SetPosition( {0, 0} );
1249 if( fp->GetLayer() !=
F_Cu )
1250 fp->Flip( fp->GetPosition(),
false );
1252 fp->SetOrientation(
ANGLE_0 );
1259 wxLogError(
"Footprint %s not found in dictionary",
1260 fp->GetFPID().GetLibItemName().wx_str() );
1264 auto entry = std::make_unique<struct BOM_ENTRY>();
1270 entry->m_OEMDesignRef = it->second;
1274 wxLogError(
"Footprint %s not found in OEMRef dictionary",
1275 fp->GetFPID().GetLibItemName().wx_str() );
1278 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1280 entry->m_pads = fp->GetPadCount();
1285 entry->m_type =
"DOCUMENT";
1287 entry->m_type =
"ELECTRICAL";
1289 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1292 ( *bom_iter )->m_count++;
1296 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1300 ( *bom_iter )->m_refdes->push_back( refdes );
1304 for(
PCB_FIELD* prop : fp->GetFields() )
1308 if( prop->IsMandatoryField() && !prop->IsValue() )
1311 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1315 if( bom_entries.empty() )
1320 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1321 m_xml_root->InsertChild( bomNode, aEcadNode );
1324 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1328 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1331 for(
const auto& entry : bom_entries )
1333 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1334 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1335 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1336 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1337 addAttribute( bomEntryNode,
"category", entry->m_type );
1339 for(
const REFDES& refdes : *( entry->m_refdes ) )
1341 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1344 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1345 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1348 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1349 addAttribute( characteristicsNode,
"category", entry->m_type );
1351 for(
const auto& prop : *( entry->m_props ) )
1353 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1354 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1355 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1356 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1374 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1385 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1425 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1466 aLayer ==
F_Cu ?
"TOP"
1467 : aLayer ==
B_Cu ?
"BOTTOM"
1483 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1484 std::set<PCB_LAYER_ID> added_layers;
1486 for(
int i = 0; i < stackup.
GetCount(); i++ )
1493 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1495 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1498 if( ly_name.IsEmpty() )
1506 ly_name = wxString::Format(
"DIELECTRIC_%d",
1511 ly_name =
genString( ly_name,
"LAYER" );
1518 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1520 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1544 added_layers.insert( layer );
1545 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1566 for(
PAD*
pad : fp->Pads() )
1568 if(
pad->HasDrilledHole() )
1570 else if(
pad->HasHole() )
1577 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1578 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
1583 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1590 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1591 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
1597 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1606 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1613 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1633 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1640 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1641 xformNode->AddAttribute(
"rotation",
1649 addShape( padNode, *aPad, aLayer );
1653 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1666 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1687 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1694 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1702 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1703 padStackHoleNode->AddAttribute(
"name",
1704 wxString::Format(
"%s%d_%d",
1705 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PTH" :
"NPTH",
1710 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
1725 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1727 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1732 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1735 addShape( padStackPadDefNode, shape );
1739 addShape( padStackPadDefNode, *aPad, layer );
1751 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
1758 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1763 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1766 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
1779 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1783 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1785 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1788 addShape( padStackPadDefNode, shape );
1797 wxXmlNode* polygonNode =
nullptr;
1799 if( aPolygon.empty() || aPolygon[0].PointCount() < 3 )
1805 polygonNode =
appendNode( aParentNode,
"Polygon" );
1806 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
1808 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
1809 addXY( polybeginNode, pts[0] );
1811 for(
size_t ii = 1; ii < pts.size(); ++ii )
1813 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
1814 addXY( polyNode, pts[ii] );
1817 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
1818 addXY( polyendNode, pts[0] );
1822 if( aFillType == FILL_T::NO_FILL )
1829 addLineDesc( polygonNode, aWidth, aDashType,
true );
1833 wxCHECK( aWidth == 0,
false );
1846 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
1848 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
1850 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
1851 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
1853 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
1854 addXY( polybeginNode, hole[0] );
1856 for(
size_t jj = 1; jj < hole.size(); ++jj )
1858 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
1859 addXY( polyNode, hole[jj] );
1862 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
1863 addXY( polyendNode, hole[0] );
1876 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
1883 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
1886 if( !outlineNode->GetChildren() )
1888 aParentNode->RemoveChild( outlineNode );
1900 int aOutline,
FILL_T aFillType,
int aWidth,
1906 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
1911 if( aFillType != FILL_T::NO_FILL )
1916 aParentNode->RemoveChild( contourNode );
1931 wxLogError(
"Failed to get board outline" );
1935 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
1939 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
1940 aStepNode->RemoveChild( profileNode );
1948 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
1949 fp->SetParentGroup(
nullptr );
1950 fp->SetPosition( { 0, 0 } );
1952 if( fp->GetLayer() !=
F_Cu )
1953 fp->Flip( fp->GetPosition(),
false );
1955 fp->SetOrientation(
ANGLE_0 );
1959 fp->GetFPID().GetLibItemName().wx_str(),
1963 addAttribute( aContentNode,
"packageRef", iter->second );
1970 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
1971 wxXmlNode* otherSideViewNode =
nullptr;
1977 if( fp->FindPadByNumber(
"1" ) )
1979 else if ( fp->FindPadByNumber(
"A1" ) )
1981 else if ( fp->FindPadByNumber(
"A" ) )
1983 else if ( fp->FindPadByNumber(
"a" ) )
1985 else if ( fp->FindPadByNumber(
"a1" ) )
1987 else if ( fp->FindPadByNumber(
"Anode" ) )
1989 else if ( fp->FindPadByNumber(
"ANODE" ) )
1994 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2004 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2006 LINE_STYLE::SOLID );
2015 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2019 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2021 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2039 if( shape->
GetShape() == SHAPE_T::CIRCLE || shape->
GetShape() == SHAPE_T::RECTANGLE )
2043 elements[item->GetLayer()][is_abs].push_back( item );
2046 auto add_base_node =
2049 wxXmlNode* parent = packageNode;
2054 if( !otherSideViewNode )
2055 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2057 parent = otherSideViewNode;
2063 name =
"SilkScreen";
2064 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2065 name =
"AssemblyDrawing";
2073 auto add_marking_node =
2074 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2076 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2078 return marking_node;
2081 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2082 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2086 if( elements.find( layer ) != elements.end() )
2088 if( elements[layer][
true].size() > 0 )
2089 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2090 else if( elements[layer][
false].size() > 0 )
2091 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2095 for(
auto& [layer, map] : elements )
2097 wxXmlNode* layer_node = add_base_node( layer );
2098 wxXmlNode* marking_node = add_marking_node( layer_node );
2099 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2100 bool update_bbox =
false;
2104 layer_nodes[layer] = layer_node;
2108 for(
auto& [is_abs, vec] : map )
2112 wxXmlNode* output_node =
nullptr;
2115 layer_bbox[layer].Merge( item->GetBoundingBox() );
2118 output_node = add_marking_node( layer_node );
2120 output_node = group_node;
2122 switch( item->Type() )
2128 if(
text->IsKnockout() )
2142 if(
text->IsBorderEnabled() )
2145 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2147 text->GetBorderWidth() );
2168 if( group_node->GetChildren() ==
nullptr )
2170 marking_node->RemoveChild( group_node );
2171 layer_node->RemoveChild( marking_node );
2173 delete marking_node;
2177 for(
auto&[layer, bbox] : layer_bbox )
2179 if( bbox.GetWidth() > 0 )
2181 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2184 std::vector<VECTOR2I> points( 4 );
2185 points[0] = bbox.GetPosition();
2186 points[2] = bbox.GetEnd();
2187 points[1].x = points[0].x;
2188 points[1].y = points[2].y;
2189 points[3].x = points[2].x;
2190 points[3].y = points[0].y;
2192 outline[0].Append( points );
2198 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2200 PAD*
pad = fp->Pads()[ii];
2201 wxXmlNode* pinNode =
appendNode( packageNode,
"Pin" );
2209 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH )
2210 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2211 else if(
pad->IsOnCopperLayer() )
2212 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2214 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2216 if(
pad->HasHole() )
2221 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2223 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2224 xformNode->AddAttribute(
2226 floatVal(
pad->GetFPRelativeOrientation().Normalize().AsDegrees() ) );
2244 std::vector<wxXmlNode*> componentNodes;
2245 std::vector<wxXmlNode*> packageNodes;
2246 std::set<wxString> packageNames;
2248 bool generate_unique =
m_OEMRef.empty();
2252 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2254 wxXmlNode* pkg =
addPackage( componentNode, fp );
2257 packageNodes.push_back( pkg );
2263 if( !generate_unique )
2264 field = fp->GetFieldByName(
m_OEMRef );
2266 if( field && !field->
GetText().empty() )
2272 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2273 fp->GetFPID().GetLibItemName().wx_str(),
2278 wxLogError(
"Duplicate footprint pointers. Please report this bug." );
2285 else if( fp->GetAttributes() &
FP_SMD )
2290 if( fp->GetOrientation() !=
ANGLE_0 || fp->GetLayer() !=
F_Cu )
2292 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2294 if( fp->GetOrientation() !=
ANGLE_0 )
2297 floatVal( fp->GetOrientation().Normalize().AsDegrees() ) );
2300 if( fp->GetLayer() !=
F_Cu )
2304 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2306 componentNodes.push_back( componentNode );
2315 for( wxXmlNode* pkg : packageNodes )
2316 aStepNode->AddChild( pkg );
2318 for( wxXmlNode* cmp : componentNodes )
2319 aStepNode->AddChild( cmp );
2327 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2331 for(
auto& [cmp,
pin] : pin_pair )
2333 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2347 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2351 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2354 [&layers, &elements](
PCB_TRACK* aTrack )
2356 if( aTrack->Type() == PCB_VIA_T )
2358 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2360 for( PCB_LAYER_ID layer : layers )
2362 if( via->FlashLayer( layer ) )
2363 elements[layer][via->GetNetCode()].push_back( via );
2368 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2372 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2373 [ &elements ](
ZONE* zone )
2375 LSEQ zone_layers = zone->GetLayerSet().Seq();
2377 for( PCB_LAYER_ID layer : zone_layers )
2378 elements[layer][zone->GetNetCode()].push_back( zone );
2381 for(
BOARD_ITEM* item : m_board->Drawings() )
2384 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2386 elements[item->GetLayer()][0].push_back( item );
2389 for(
FOOTPRINT* fp : m_board->Footprints() )
2391 for(
PCB_FIELD* field : fp->GetFields() )
2392 elements[field->GetLayer()][0].push_back( field );
2394 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2395 elements[item->GetLayer()][0].push_back( item );
2397 for(
PAD*
pad : fp->Pads() )
2399 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2403 if(
pad->FlashLayer( layer ) )
2404 elements[layer][
pad->GetNetCode()].push_back(
pad );
2411 if( m_progressReporter )
2412 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2414 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2415 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2417 auto process_net = [&] (
int net )
2419 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
2424 std::stable_sort( vec.begin(), vec.end(),
2427 if( a->GetParentFootprint() == b->GetParentFootprint() )
2428 return a->Type() < b->Type();
2430 return a->GetParentFootprint() < b->GetParentFootprint();
2433 generateLayerSetNet( layerNode, layer, vec );
2438 if( m_progressReporter )
2440 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2441 m_board->GetLayerName( layer ),
2442 net->GetNetname() ) );
2443 m_progressReporter->AdvanceProgress();
2446 process_net( net->GetNetCode() );
2449 if( layerNode->GetChildren() ==
nullptr )
2451 aStepNode->RemoveChild( layerNode );
2464 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2465 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2476 wxLogError(
"Failed to find padstack for via" );
2480 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2483 if(
via->GetNetCode() > 0 )
2486 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2487 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2492 addXY( holeNode,
via->GetPosition() );
2501 wxLogError(
"Failed to find padstack for pad" );
2505 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2508 if(
pad->GetNetCode() > 0 )
2511 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2512 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2515 pad->GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
2518 addXY( holeNode,
pad->GetPosition() );
2527 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2528 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2532 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2534 if(
pad->GetNetCode() > 0 )
2537 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2544 std::vector<BOARD_ITEM*>& aItems )
2546 auto it = aItems.begin();
2547 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2548 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2549 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2551 bool has_via =
false;
2552 bool has_pad =
false;
2554 wxXmlNode* padSetNode =
nullptr;
2556 wxXmlNode* viaSetNode =
nullptr;
2558 wxXmlNode* teardropLayerSetNode =
nullptr;
2559 wxXmlNode* teardropFeatureSetNode =
nullptr;
2564 if( item->GetNetCode() > 0 )
2573 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
2574 shape.
SetStart( track->GetStart() );
2575 shape.
SetEnd( track->GetEnd() );
2576 shape.
SetWidth( track->GetWidth() );
2582 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2593 viaSetNode = layerSetNode;
2598 viaSetNode =
appendNode( layerSetNode,
"Set" );
2600 if( track->GetNetCode() > 0 )
2607 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2614 wxXmlNode* zoneFeatureNode = specialNode;
2616 if( zone->IsTeardropArea() &&
m_version >
'B' )
2618 if( !teardropFeatureSetNode )
2620 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
2621 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
2623 if( zone->GetNetCode() > 0 )
2626 genString( zone->GetNetname(),
"NET" ) );
2629 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
2631 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
2634 zoneFeatureNode = teardropFeatureSetNode;
2640 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2641 wxString refDes =
componentName( zone->GetParentFootprint() );
2643 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
2645 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
2649 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
2651 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
2662 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2665 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
2669 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2674 else if( shape->GetShape() == SHAPE_T::CIRCLE
2675 || shape->GetShape() == SHAPE_T::RECTANGLE
2676 || shape->GetShape() == SHAPE_T::POLY )
2678 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2680 if( shape->GetNetCode() > 0 )
2683 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2700 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2702 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2707 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2715 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
2716 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
2718 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
2720 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2726 addText( tempFeature, text_item,
text->GetFontMetrics() );
2744 padSetNode = layerSetNode;
2749 padSetNode =
appendNode( aLayerNode,
"Set" );
2751 if(
pad->GetNetCode() > 0 )
2766 switch( item->Type() )
2771 add_track(
static_cast<PCB_TRACK*
>( item ) );
2779 add_pad(
static_cast<PAD*
>( item ) );
2783 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
2808 if( specialNode->GetChildren() ==
nullptr )
2810 featureSetNode->RemoveChild( specialNode );
2814 if( featureSetNode->GetChildren() ==
nullptr )
2816 layerSetNode->RemoveChild( featureSetNode );
2817 delete featureSetNode;
2820 if( layerSetNode->GetChildren() ==
nullptr )
2822 aLayerNode->RemoveChild( layerSetNode );
2823 delete layerSetNode;
2836 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
2840 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
2843 std::set<wxString> unique_parts;
2844 std::map<wxString,wxString> unique_vendors;
2848 auto [ it, success ] = unique_parts.insert(
name );
2853 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
2857 PCB_FIELD* company[2] = { fp->GetFieldByName(
m_mfg ),
nullptr };
2860 for (
int ii = 0; ii < 2; ++ii )
2866 if( mpn_name.empty() )
2869 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
2873 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
2876 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
2878 wxString
name = wxT(
"UNKNOWN" );
2881 if( !ii && company[ii] )
2889 else if( !ii && !company_name[ii].
empty() )
2891 name = company_name[ii];
2893 else if( ii && !
m_dist.empty() )
2898 auto [vendor_id, inserted] = unique_vendors.emplace(
2900 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
2902 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
2906 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
2929 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
2931 if( it->second ==
"inch" )
2938 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
2939 m_sigfig = std::stoi( it->second );
2941 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
2944 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
2947 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
2948 m_mpn = it->second.wx_str();
2950 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
2951 m_mfg = it->second.wx_str();
2953 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
2954 m_dist = it->second.wx_str();
2956 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
2961 for(
char c =
'a'; c <=
'z'; ++c )
2964 for(
char c =
'A'; c <=
'Z'; ++c )
2967 for(
char c =
'0'; c <=
'9'; ++c )
2971 std::string specialChars =
"_\\-.+><";
2973 for(
char c : specialChars )
3002 double written_bytes = 0.0;
3003 double last_yield = 0.0;
3010 auto update_progress = [&](
size_t aBytes )
3012 written_bytes += aBytes;
3013 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
3018 if( last_yield + 0.01 < percent )
3020 last_yield = percent;
3030 wxLogError(
_(
"Failed to save file to buffer" ) );
3034 size_t size = out_stream.GetSize();
constexpr int ARC_HIGH_DEF
constexpr double PCB_IU_PER_MM
bool IsPrmSpecified(const wxString &aPrmValue)
@ BS_ITEM_TYPE_DIELECTRIC
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
wxString GetLayerName() const
PCB_LAYER_ID GetBrdLayerId() const
BOARD_STACKUP_ITEM_TYPE GetType() const
int GetDielectricLayerId() 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.
Information pertinent to a Pcbnew printed circuit board.
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
const NETINFO_LIST & GetNetInfo() const
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
const wxString & GetFileName() const
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
BOARD_DESIGN_SETTINGS & GetDesignSettings() 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.
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,...
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
KIFONT::FONT * GetFont() const
virtual EDA_ANGLE GetDrawRotation() 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.
PROGRESS_REPORTER * m_progressReporter
Progress reporter to track the progress of the operation, may be nullptr.
FONT is an abstract base class for both outline and stroke fonts.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr)
A color representation with 4 components: red, green, blue, alpha.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
LSET is a set of PCB_LAYER_IDs.
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Handle the data for a net.
const wxString & GetNetname() const
Container for NETINFO_ITEM elements, which are the nets.
NETINFO_ITEM * GetNetItem(int aNetCode) const
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
int GetSolderMaskExpansion() const
int GetDrillSizeY() const
const VECTOR2I & GetDrillSize() const
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
int GetRoundRectCornerRadius() const
VECTOR2I GetPosition() const override
const VECTOR2I & GetOffset() const
int GetDrillSizeX() const
const VECTOR2I & GetDelta() const
PAD_SHAPE GetShape() const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
VECTOR2I GetSolderPasteMargin() const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
int GetChamferPositions() const
bool HasDrilledHole() const override
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
bool HasHole() const override
const VECTOR2I & GetSize() const
double GetChamferRectRatio() const
const VECTOR2I & GetMid() const
void addText(wxXmlNode *aContentNode, EDA_TEXT *aShape, const KIFONT::METRICS &aFontMetrics)
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 generateDrillLayers(wxXmlNode *aCadLayerNode)
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)
bool addOutlineNode(wxXmlNode *aParentNode, const SHAPE_POLY_SET &aPolySet, 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 addVia(wxXmlNode *aContentNode, const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
void addSlotCavity(wxXmlNode *aContentNode, const PAD &aPad, const wxString &aName)
wxXmlNode * m_last_padstack
size_t lineHash(int aWidth, LINE_STYLE aDashType)
std::map< size_t, wxString > m_std_shape_dict
void addAttribute(wxXmlNode *aNode, const wxString &aName, const wxString &aValue)
wxXmlNode * m_shape_user_node
wxXmlNode * generateAvlSection()
Creates the Approved Vendor List section.
wxXmlNode * generateHistorySection()
Creates the history section.
void addXY(wxXmlNode *aNode, const VECTOR2I &aVec, const char *aXName=nullptr, const char *aYName=nullptr)
wxXmlNode * m_shape_std_node
void addPadStack(wxXmlNode *aContentNode, const PAD *aPad)
std::map< FOOTPRINT *, wxString > m_OEMRef_dict
void clearLoadedFootprints()
Frees the memory allocated for the loaded footprints in m_loaded_footprints.
std::map< 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::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)
wxXmlNode * generateBOMSection(wxXmlNode *aEcadNode)
Creates the BOM section.
wxXmlNode * generateContentStackup(wxXmlNode *aContentNode)
void addShape(wxXmlNode *aContentNode, const PCB_SHAPE &aShape)
void addCadHeader(wxXmlNode *aEcadNode)
std::vector< FOOTPRINT * > GetImportedCachedLibraryFootprints() override
Return a container with the cached library footprints generated in the last call to Load.
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
wxString floatVal(double aVal)
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const STRING_UTF8_MAP *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::vector< FOOTPRINT * > m_loaded_footprints
bool addPolygonCutouts(wxXmlNode *aParentNode, const SHAPE_POLY_SET::POLYGON &aPolygon)
std::set< wxUniChar > m_acceptable_chars
void addLayerAttributes(wxXmlNode *aNode, PCB_LAYER_ID aLayer)
wxXmlNode * generateXmlHeader()
Creates the XML header for IPC-2581.
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
void addLocationNode(wxXmlNode *aContentNode, double aX, double aY)
bool addPolygonNode(wxXmlNode *aParentNode, const SHAPE_POLY_SET::POLYGON &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE, int aWidth=0, LINE_STYLE aDashType=LINE_STYLE::SOLID)
std::map< int, std::vector< std::pair< wxString, wxString > > > m_net_pin_dict
std::map< FOOTPRINT *, wxString > m_footprint_refdes_reverse_dict
wxXmlNode * m_enterpriseNode
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
STROKE_PARAMS GetStroke() const override
VECTOR2I GetPosition() const override
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
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
VECTOR2I GetPosition() const override
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
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.
virtual void SetNumPhases(int aNumPhases)=0
Set the number of phases.
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void BeginPhase(int aPhase)=0
Initialize the aPhase virtual zone of the dialog progress bar.
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
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.
Represent a set of closed polygons.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
A name/value tuple with unique names and optional values.
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
static bool empty(const wxTextEntryBase *aCtrl)
static constexpr EDA_ANGLE ANGLE_0
static const wxChar traceIpc2581[]
This program source code file is part of KiCad, a free EDA CAD application.
static std::size_t hash_val(const Types &... args)
static void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
@ HASH_POS
use coordinates relative to the parent object
@ REL_COORD
use coordinates relative to the shape position
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
bool IsCopperLayer(int aLayerId)
Tests 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.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
std::vector< FAB_LAYER_COLOR > dummy
const std::vector< FAB_LAYER_COLOR > & GetStandardColors(BOARD_STACKUP_ITEM_TYPE aType)
LINE_STYLE
Dashed line types.
@ 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
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D