54#include <wx/numformatter.h>
55#include <wx/mstream.h>
56#include <wx/xml/xml.h>
77 std::vector<FOOTPRINT*> retval;
81 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
92 if( aParent->GetChildren() )
93 aNode->SetNext( aParent->GetChildren() );
95 aNode->SetNext(
nullptr );
97 aParent->SetChildren( aNode );
98 aNode->SetParent( aParent );
107 aNode->SetNext( aPrev->GetNext() );
108 aPrev->SetNext( aNode );
109 aNode->SetParent( aPrev->GetParent() );
118 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
130 static wxXmlNode* lastNode =
nullptr;
132 if( lastNode && lastNode->GetParent() == aParent && lastNode->GetNext() ==
nullptr )
134 aNode->SetParent( aParent );
135 lastNode->SetNext( aNode );
139 aParent->AddChild( aNode );
151 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
165 str.Replace( wxT(
":" ), wxT(
"_" ) );
168 str.Prepend( wxString( aPrefix ) + wxT(
":" ) );
170 str.Prepend( wxT(
"KI:" ) );
175 str = wxString::Format(
"%s_", aPrefix );
177 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
197 if(
name.empty() && fp )
201 if( fp->
Pads()[ii] == aPad )
209 name = wxString::Format(
"NPTH%zu", ii );
210 else if(
name.empty() )
211 name = wxString::Format(
"PAD%zu", ii );
220 [&](
const wxString& aName )
239 wxString
name = baseName;
242 while( !tryInsert(
name ) )
244 name = wxString::Format(
"%s_%d", baseName, suffix++ );
255 wxString str = wxString::FromCDouble( aVal,
m_sigfig );
258 while( str.EndsWith( wxT(
"00" ) ) )
262 if( str == wxT(
"-0.0" ) )
287 aNode->AddAttribute( aName, aValue );
294 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
296 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
297 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
298 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
301 addAttribute( xmlHeaderNode,
"xsi:schemaLocation",
"http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd");
303 addAttribute( xmlHeaderNode,
"xsi:schemaLocation",
"http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd");
307 return xmlHeaderNode;
318 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
333 contentNode->AddChild( color_node );
337 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
357 contentNode->AddChild( color_node );
366 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
393 case SHAPE_T::RECTANGLE:
398 case SHAPE_T::CIRCLE:
404 case SHAPE_T::BEZIER:
405 case SHAPE_T::SEGMENT:
410 case SHAPE_T::UNDEFINED:
439 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
443 wxString layer_name = item->GetLayerName();
444 int sub_layer_count = 1;
446 if( layer_name.empty() )
449 layer_name =
genString( layer_name,
"LAYER" );
454 wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
"LAYER" );
455 sub_layer_count = item->GetSublayersCount();
462 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
464 wxString sub_layer_name = layer_name;
467 sub_layer_name += wxString::Format(
"_%d", sub_idx );
469 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
475 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
479 wxString colorName = item->GetColor( sub_idx );
481 if( colorName.StartsWith( wxT(
"#" ) ) )
484 COLOR4D layer_color( colorName );
493 if( fab_color.GetName() == colorName )
511 if( aFill == FILL_T::FILLED_SHAPE )
517 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
523 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
524 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
531 wxCHECK_RET( aNode,
"aNode is null" );
536 wxXmlNode* entry_node =
nullptr;
540 size_t hash =
lineHash( aWidth, aDashType );
541 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
545 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
560 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
566 case LINE_STYLE::DOT:
569 case LINE_STYLE::DASH:
572 case LINE_STYLE::DASHDOT:
575 case LINE_STYLE::DASHDOTDOT:
597 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
602 std::list<VECTOR2I> pts;
604 auto push_pts = [&]()
609 wxXmlNode* line_node =
nullptr;
616 addXY( line_node, pts.front(),
"startX",
"startY" );
617 addXY( line_node, pts.back(),
"endX",
"endY" );
621 line_node =
appendNode( text_node,
"Polyline" );
622 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
623 addXY( point_node, pts.front() );
625 auto iter = pts.begin();
627 for( ++iter; iter != pts.end(); ++iter )
629 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
630 addXY( point_node, *iter );
644 if( aPt1 == pts.back() )
645 pts.push_back( aPt2 );
646 else if( aPt2 == pts.front() )
647 pts.push_front( aPt1 );
648 else if( aPt1 == pts.front() )
649 pts.push_front( aPt2 );
650 else if( aPt2 == pts.back() )
651 pts.push_back( aPt1 );
655 pts.push_back( aPt1 );
656 pts.push_back( aPt2 );
661 pts.push_back( aPt1 );
662 pts.push_back( aPt2 );
668 if( aPoly.PointCount() < 3 )
671 wxXmlNode* outline_node = appendNode( text_node,
"Outline" );
672 wxXmlNode* poly_node = appendNode( outline_node,
"Polygon" );
675 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
676 wxXmlNode* point_node = appendNode( poly_node,
"PolyBegin" );
677 addXY( point_node, pts.front() );
679 for(
size_t ii = 1; ii < pts.size(); ++ii )
681 wxXmlNode* point_node =
682 appendNode( poly_node,
"PolyStepSegment" );
683 addXY( point_node, pts[ii] );
686 point_node = appendNode( poly_node,
"PolyStepSegment" );
687 addXY( point_node, pts.front() );
692 font->Draw( &callback_gal, aText->GetShownText(
true ), aText->GetTextPos(), attrs, aFontMetrics );
697 if( text_node->GetChildren() == nullptr )
699 aContentNode->RemoveChild( text_node );
712 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
729 case PAD_SHAPE::CIRCLE:
737 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
738 circle_node->AddAttribute(
744 case PAD_SHAPE::RECTANGLE:
752 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
760 case PAD_SHAPE::OVAL:
768 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
776 case PAD_SHAPE::ROUNDRECT:
784 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
788 roundrect_node->AddAttribute(
"radius",
798 case PAD_SHAPE::CHAMFERED_RECT:
806 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
811 int shorterSide = std::min( pad_size.
x, pad_size.
y );
830 case PAD_SHAPE::TRAPEZOID:
842 int dx = pad_size.
x / 2;
843 int dy = pad_size.
y / 2;
844 int ddx = trap_delta.
x / 2;
845 int ddy = trap_delta.
y / 2;
847 outline.
Append( -dx - ddy, dy + ddx );
848 outline.
Append( dx + ddy, dy - ddx );
849 outline.
Append( dx - ddy, -dy + ddx );
850 outline.
Append( -dx + ddy, -dy - ddx );
864 case PAD_SHAPE::CUSTOM:
878 CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
886 wxLogError(
"Unknown pad type" );
893 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
907 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
914 case SHAPE_T::CIRCLE:
925 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
927 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
945 case SHAPE_T::RECTANGLE:
952 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
959 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
975 width += stroke_width;
976 height += stroke_width;
998 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1007 addContourNode( special_node, poly_set, ii, FILL_T::FILLED_SHAPE, 0,
1008 LINE_STYLE::SOLID );
1020 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1022 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1037 case SHAPE_T::BEZIER:
1039 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1043 std::vector<VECTOR2I> points;
1046 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1047 addXY( point_node, points[0] );
1049 for(
size_t i = 1; i < points.size(); i++ )
1051 wxXmlNode* point_node =
1052 appendNode( polyline_node,
"PolyStepSegment" );
1053 addXY( point_node, points[i] );
1065 case SHAPE_T::SEGMENT:
1067 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1069 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1080 case SHAPE_T::UNDEFINED:
1086 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1095 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1115 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1123 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1125 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1128 return logisticNode;
1139 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1141 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1143 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1144 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1145 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1148 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1151 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1153 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1154 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1175 m_refdes =
new std::vector<REFDES>();
1176 m_props =
new std::map<wxString, wxString>();
1187 wxString m_OEMDesignRef;
1191 std::vector<REFDES>* m_refdes;
1192 std::map<wxString, wxString>* m_props;
1195 std::set<std::unique_ptr<struct BOM_ENTRY>, std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1196 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
const std::unique_ptr<struct BOM_ENTRY>& b )
1198 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1203 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1204 fp->SetParentGroup(
nullptr );
1205 fp->SetPosition( {0, 0} );
1207 if( fp->GetLayer() !=
F_Cu )
1208 fp->Flip( fp->GetPosition(),
false );
1210 fp->SetOrientation(
ANGLE_0 );
1217 wxLogError(
"Footprint %s not found in dictionary", fp->GetFPID().GetLibItemName().wx_str() );
1221 auto entry = std::make_unique<struct BOM_ENTRY>();
1227 entry->m_OEMDesignRef = it->second;
1231 wxLogError(
"Footprint %s not found in OEMRef dictionary", fp->GetFPID().GetLibItemName().wx_str() );
1234 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1236 entry->m_pads = fp->GetPadCount();
1241 entry->m_type =
"DOCUMENT";
1243 entry->m_type =
"ELECTRICAL";
1245 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1248 ( *bom_iter )->m_count++;
1252 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1256 ( *bom_iter )->m_refdes->push_back( refdes );
1260 for(
PCB_FIELD* prop : fp->GetFields() )
1264 if( prop->IsMandatoryField() && !prop->IsValue() )
1267 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1271 if( bom_entries.empty() )
1276 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1277 m_xml_root->InsertChild( bomNode, aEcadNode );
1280 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1284 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1287 for(
const auto& entry : bom_entries )
1289 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1290 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1291 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1292 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1293 addAttribute( bomEntryNode,
"category", entry->m_type );
1295 for(
const REFDES& refdes : *( entry->m_refdes ) )
1297 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1300 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1301 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1304 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1305 addAttribute( characteristicsNode,
"category", entry->m_type );
1307 for(
const auto& prop : *( entry->m_props ) )
1309 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1310 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1311 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1312 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1330 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1341 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1381 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1422 aLayer ==
F_Cu ?
"TOP"
1423 : aLayer ==
B_Cu ?
"BOTTOM"
1439 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1440 std::set<PCB_LAYER_ID> added_layers;
1442 for(
int i = 0; i < stackup.
GetCount(); i++ )
1449 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1451 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1454 if( ly_name.IsEmpty() )
1464 ly_name =
genString( ly_name,
"LAYER" );
1471 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1473 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1497 added_layers.insert( layer );
1498 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1519 for(
PAD*
pad : fp->Pads() )
1521 if(
pad->HasHole() &&
pad->GetDrillSizeX() !=
pad->GetDrillSizeY() )
1523 else if(
pad->HasHole() )
1530 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1531 drillNode->AddAttribute(
"name",
genString( wxString::Format(
"%s_%s",
1538 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1545 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1546 drillNode->AddAttribute(
"name",
genString( wxString::Format(
"%s_%s",
1554 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1563 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1570 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1589 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1596 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1597 xformNode->AddAttribute(
"rotation",
1605 addShape( padNode, *aPad, aLayer );
1609 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1621 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1626 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1639 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1646 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1654 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1655 padStackHoleNode->AddAttribute(
"name", wxString::Format(
"%s%d_%d",
1656 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PTH" :
"NPTH",
1660 addAttribute( padStackHoleNode,
"platingStatus", aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
1675 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1677 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1682 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1685 addShape( padStackPadDefNode, shape );
1689 addShape( padStackPadDefNode, *aPad, layer );
1700 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
1707 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1712 wxXmlNode* padStackHoleNode =
1713 appendNode( padStackDefNode,
"PadstackHoleDef" );
1715 padStackHoleNode->AddAttribute(
"diameter",
1717 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
1730 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1734 wxXmlNode* padStackPadDefNode =
1735 appendNode( padStackDefNode,
"PadstackPadDef" );
1737 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1740 addShape( padStackPadDefNode, shape );
1749 wxXmlNode* polygonNode =
nullptr;
1751 if( aPolygon.empty() || aPolygon[0].PointCount() < 3 )
1757 polygonNode =
appendNode( aParentNode,
"Polygon" );
1758 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
1760 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
1761 addXY( polybeginNode, pts[0] );
1763 for(
size_t ii = 1; ii < pts.size(); ++ii )
1765 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
1766 addXY( polyNode, pts[ii] );
1769 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
1770 addXY( polyendNode, pts[0] );
1774 if( aFillType == FILL_T::NO_FILL )
1781 addLineDesc( polygonNode, aWidth, aDashType,
true );
1785 wxCHECK( aWidth == 0,
false );
1797 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
1799 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
1801 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
1802 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
1804 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
1805 addXY( polybeginNode, hole[0] );
1807 for(
size_t jj = 1; jj < hole.size(); ++jj )
1809 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
1810 addXY( polyNode, hole[jj] );
1813 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
1814 addXY( polyendNode, hole[0] );
1826 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
1833 wxLogDebug(
"Failed to add polygon to outline" );
1836 if( !outlineNode->GetChildren() )
1838 aParentNode->RemoveChild( outlineNode );
1850 int aOutline,
FILL_T aFillType,
int aWidth,
1856 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
1861 if( aFillType != FILL_T::NO_FILL )
1866 aParentNode->RemoveChild( contourNode );
1881 wxLogError(
"Failed to get board outline" );
1885 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
1888 wxLogDebug(
"Failed to add polygon to profile" );
1889 aStepNode->RemoveChild( profileNode );
1897 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
1898 fp->SetParentGroup(
nullptr );
1899 fp->SetPosition( { 0, 0 } );
1901 if( fp->GetLayer() !=
F_Cu )
1902 fp->Flip( fp->GetPosition(),
false );
1904 fp->SetOrientation(
ANGLE_0 );
1908 wxString
name =
genString( wxString::Format(
"%s_%zu", fp->GetFPID().GetLibItemName().wx_str(),
1912 addAttribute( aContentNode,
"packageRef", iter->second );
1919 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
1920 wxXmlNode* otherSideViewNode =
nullptr;
1926 if( fp->FindPadByNumber(
"1" ) )
1928 else if ( fp->FindPadByNumber(
"A1" ) )
1930 else if ( fp->FindPadByNumber(
"A" ) )
1932 else if ( fp->FindPadByNumber(
"a" ) )
1934 else if ( fp->FindPadByNumber(
"a1" ) )
1936 else if ( fp->FindPadByNumber(
"Anode" ) )
1938 else if ( fp->FindPadByNumber(
"ANODE" ) )
1943 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
1953 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
1963 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
1967 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
1969 for(
BOARD_ITEM* item : fp->GraphicalItems() )
1987 if( shape->
GetShape() == SHAPE_T::CIRCLE || shape->
GetShape() == SHAPE_T::RECTANGLE )
1991 elements[item->GetLayer()][is_abs].push_back( item );
1994 auto add_base_node = [&](
PCB_LAYER_ID aLayer ) -> wxXmlNode*
1996 wxXmlNode* parent = packageNode;
2001 if( !otherSideViewNode )
2002 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2004 parent = otherSideViewNode;
2010 name =
"SilkScreen";
2011 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2012 name =
"AssemblyDrawing";
2020 auto add_marking_node = [&]( wxXmlNode* aNode ) -> wxXmlNode*
2022 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2024 return marking_node;
2027 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2028 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2032 if( elements.find( layer ) != elements.end() )
2034 if( elements[layer][
true].size() > 0 )
2035 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2036 else if( elements[layer][
false].size() > 0 )
2037 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2041 for(
auto& [layer, map] : elements )
2043 wxXmlNode* layer_node = add_base_node( layer );
2044 wxXmlNode* marking_node = add_marking_node( layer_node );
2045 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2046 bool update_bbox =
false;
2050 layer_nodes[layer] = layer_node;
2054 for(
auto& [is_abs, vec] : map )
2058 wxXmlNode* output_node =
nullptr;
2061 layer_bbox[layer].Merge( item->GetBoundingBox() );
2064 output_node = add_marking_node( layer_node );
2066 output_node = group_node;
2068 switch( item->Type() )
2083 if(
text->IsBorderEnabled() )
2086 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2088 text->GetBorderWidth() );
2109 if( group_node->GetChildren() ==
nullptr )
2111 marking_node->RemoveChild( group_node );
2112 layer_node->RemoveChild( marking_node );
2114 delete marking_node;
2118 for(
auto&[layer, bbox] : layer_bbox)
2120 if( bbox.GetWidth() > 0 )
2122 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2125 std::vector<VECTOR2I> points( 4 );
2126 points[0] = bbox.GetPosition();
2127 points[2] = bbox.GetEnd();
2128 points[1].x = points[0].x;
2129 points[1].y = points[2].y;
2130 points[3].x = points[2].x;
2131 points[3].y = points[0].y;
2133 outline[0].Append( points );
2139 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2141 PAD*
pad = fp->Pads()[ii];
2142 wxXmlNode* pinNode =
appendNode( packageNode,
"Pin" );
2150 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH )
2151 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2152 else if(
pad->IsOnCopperLayer() )
2153 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2155 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2157 if(
pad->HasHole() )
2162 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2164 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2165 xformNode->AddAttribute(
2167 floatVal(
pad->GetFPRelativeOrientation().Normalize().AsDegrees() ) );
2185 std::vector<wxXmlNode*> componentNodes;
2186 std::vector<wxXmlNode*> packageNodes;
2187 std::set<wxString> packageNames;
2189 bool generate_unique =
m_OEMRef.empty();
2193 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2195 wxXmlNode* pkg =
addPackage( componentNode, fp );
2198 packageNodes.push_back( pkg );
2204 if( !generate_unique )
2205 field = fp->GetFieldByName(
m_OEMRef );
2207 if( field && !field->
GetText().empty() )
2213 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2214 fp->GetFPID().GetLibItemName().wx_str(),
2219 wxLogError(
"Duplicate footprint pointers. Please report this bug." );
2226 else if( fp->GetAttributes() &
FP_SMD )
2231 if( fp->GetOrientation() !=
ANGLE_0 || fp->GetLayer() !=
F_Cu )
2233 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2235 if( fp->GetOrientation() !=
ANGLE_0 )
2236 addAttribute( xformNode,
"rotation",
floatVal( fp->GetOrientation().Normalize().AsDegrees() ) );
2238 if( fp->GetLayer() !=
F_Cu )
2242 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2244 componentNodes.push_back( componentNode );
2253 for( wxXmlNode* pkg : packageNodes )
2254 aStepNode->AddChild( pkg );
2256 for( wxXmlNode* cmp : componentNodes )
2257 aStepNode->AddChild( cmp );
2264 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2267 for(
auto& [cmp,
pin] : pin_pair )
2269 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2283 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2287 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2291 [&layers, &elements](
PCB_TRACK* aTrack )
2293 if( aTrack->Type() == PCB_VIA_T )
2295 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2297 for( PCB_LAYER_ID layer : layers )
2299 if( via->FlashLayer( layer ) )
2300 elements[layer][via->GetNetCode()].push_back( via );
2305 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2309 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2310 [ &elements ](
ZONE* zone )
2312 LSEQ zone_layers = zone->GetLayerSet().Seq();
2314 for( PCB_LAYER_ID layer : zone_layers )
2316 elements[layer][zone->GetNetCode()].push_back( zone );
2320 for(
BOARD_ITEM* item : m_board->Drawings() )
2323 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2325 elements[item->GetLayer()][0].push_back( item );
2328 for(
FOOTPRINT* fp : m_board->Footprints() )
2330 for(
PCB_FIELD* field : fp->GetFields() )
2331 elements[field->GetLayer()][0].push_back( field );
2333 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2334 elements[item->GetLayer()][0].push_back( item );
2336 for(
PAD*
pad : fp->Pads() )
2338 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2342 if(
pad->FlashLayer( layer ) )
2343 elements[layer][
pad->GetNetCode()].push_back(
pad );
2350 if( m_progressReporter )
2351 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2353 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2354 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2358 if( m_progressReporter )
2360 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2361 m_board->GetLayerName( layer ),
2362 net->GetNetname() ) );
2363 m_progressReporter->AdvanceProgress();
2366 std::vector<BOARD_ITEM*>& vec = elements[layer][net->GetNetCode()];
2368 std::stable_sort( vec.begin(), vec.end(),
2371 if( a->GetParentFootprint() == b->GetParentFootprint() )
2372 return a->Type() < b->Type();
2374 return a->GetParentFootprint() < b->GetParentFootprint();
2380 generateLayerSetNet( layerNode, layer, vec );
2383 if( layerNode->GetChildren() ==
nullptr )
2385 aStepNode->RemoveChild( layerNode );
2397 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2398 layerNode->AddAttribute(
"layerRef",
genString(
2399 wxString::Format(
"%s_%s",
2413 wxLogError(
"Failed to find padstack for via" );
2417 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2420 if(
via->GetNetCode() > 0 )
2423 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2424 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2429 addXY( holeNode,
via->GetPosition() );
2439 wxLogError(
"Failed to find padstack for pad" );
2443 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2446 if(
pad->GetNetCode() > 0 )
2449 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2450 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2452 addAttribute( holeNode,
"platingStatus",
pad->GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
2455 addXY( holeNode,
pad->GetPosition() );
2463 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2464 layerNode->AddAttribute(
"layerRef",
genString(
2465 wxString::Format(
"%s_%s",
2472 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2474 if(
pad->GetNetCode() > 0 )
2477 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2484 std::vector<BOARD_ITEM*>& aItems )
2486 auto it = aItems.begin();
2487 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2488 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2489 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2491 bool has_via =
false;
2492 bool has_pad =
false;
2494 wxXmlNode* padSetNode =
nullptr;
2496 wxXmlNode* viaSetNode =
nullptr;
2498 wxXmlNode* teardropLayerSetNode =
nullptr;
2499 wxXmlNode* teardropFeatureSetNode =
nullptr;
2503 if( item->GetNetCode() > 0 )
2506 auto add_track = [&](
PCB_TRACK* track )
2510 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
2511 shape.
SetStart( track->GetStart() );
2512 shape.
SetEnd( track->GetEnd() );
2513 shape.
SetWidth( track->GetWidth() );
2519 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2530 viaSetNode = layerSetNode;
2535 viaSetNode =
appendNode( layerSetNode,
"Set" );
2537 if( track->GetNetCode() > 0 )
2544 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2550 wxXmlNode* zoneFeatureNode = specialNode;
2552 if( zone->IsTeardropArea() &&
m_version >
'B' )
2554 if( !teardropFeatureSetNode )
2556 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
2557 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
2559 if( zone->GetNetCode() > 0 )
2562 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
2564 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
2567 zoneFeatureNode = teardropFeatureSetNode;
2573 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2574 wxString refDes =
componentName( zone->GetParentFootprint() );
2576 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
2578 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
2582 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
2584 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
2588 auto add_shape = [&] (
PCB_SHAPE* shape )
2594 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2597 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
2601 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2606 else if( shape->GetShape() == SHAPE_T::CIRCLE || shape->GetShape() == SHAPE_T::RECTANGLE || shape->GetShape() == SHAPE_T::POLY )
2608 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2610 if( shape->GetNetCode() > 0 )
2613 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2629 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2631 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2636 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2644 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
2645 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
2647 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
2649 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2651 addText( tempFeature, text_item,
text->GetFontMetrics() );
2662 auto add_pad = [&](
PAD*
pad )
2668 padSetNode = layerSetNode;
2673 padSetNode =
appendNode( aLayerNode,
"Set" );
2675 if(
pad->GetNetCode() > 0 )
2690 switch( item->Type() )
2695 add_track(
static_cast<PCB_TRACK*
>( item ) );
2703 add_pad(
static_cast<PAD*
>( item ) );
2707 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
2727 wxLogDebug(
"Unhandled type %s",
2732 if( specialNode->GetChildren() ==
nullptr )
2734 featureSetNode->RemoveChild( specialNode );
2735 layerSetNode->RemoveChild( featureSetNode );
2736 aLayerNode->RemoveChild( layerSetNode );
2738 delete featureSetNode;
2739 delete layerSetNode;
2752 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
2756 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
2759 std::set<wxString> unique_parts;
2760 std::map<wxString,wxString> unique_vendors;
2764 auto [ it, success ] = unique_parts.insert(
name );
2769 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
2773 PCB_FIELD* company[2] = { fp->GetFieldByName(
m_mfg ),
nullptr };
2776 for (
int ii = 0; ii < 2; ++ii )
2782 if( mpn_name.empty() )
2785 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
2789 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
2792 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
2794 wxString
name = wxT(
"UNKNOWN" );
2797 if( !ii && company[ii] )
2805 else if( !ii && !company_name[ii].
empty() )
2807 name = company_name[ii];
2809 else if( ii && !
m_dist.empty() )
2814 auto [vendor_id, inserted] = unique_vendors.emplace(
2816 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
2818 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
2822 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
2845 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
2847 if( it->second ==
"inch" )
2854 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
2855 m_sigfig = std::stoi( it->second );
2857 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
2860 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
2863 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
2864 m_mpn = it->second.wx_str();
2866 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
2867 m_mfg = it->second.wx_str();
2869 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
2870 m_dist = it->second.wx_str();
2872 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
2877 for(
char c =
'a'; c <=
'z'; ++c )
2880 for(
char c =
'A'; c <=
'Z'; ++c )
2883 for(
char c =
'0'; c <=
'9'; ++c )
2887 std::string specialChars =
"_\\-.+><";
2889 for(
char c : specialChars )
2918 double written_bytes = 0.0;
2919 double last_yield = 0.0;
2926 auto update_progress = [&](
size_t aBytes )
2928 written_bytes += aBytes;
2929 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
2934 if( last_yield + 0.01 < percent )
2936 last_yield = percent;
2946 wxLogError(
_(
"Failed to save file to buffer" ) );
2950 size_t size = out_stream.GetSize();
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 aMinSegLen=0, int aMaxSegCount=32)
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...
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)
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
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)
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()
Return the automapped layers.
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)
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.
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
This program source code file is part of KiCad, a free EDA CAD application.
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.
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.
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 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
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.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
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< double > VECTOR2D