46#include <wx/numformatter.h>
47#include <wx/xml/xml.h>
75 std::vector<FOOTPRINT*> retval;
78 retval.push_back(
static_cast<FOOTPRINT*
>( fp->Clone() ) );
88 if( aParent->GetChildren() )
89 aNode->SetNext( aParent->GetChildren() );
91 aNode->SetNext(
nullptr );
93 aParent->SetChildren( aNode );
94 aNode->SetParent( aParent );
103 aNode->SetNext( aPrev->GetNext() );
104 aPrev->SetNext( aNode );
105 aNode->SetParent( aPrev->GetParent() );
114 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
126 static wxXmlNode* lastNode =
nullptr;
128 if( lastNode && lastNode->GetParent() == aParent && lastNode->GetNext() ==
nullptr )
130 aNode->SetParent( aParent );
131 lastNode->SetNext( aNode );
135 aParent->AddChild( aNode );
147 wxXmlNode* node =
new wxXmlNode( wxXML_ELEMENT_NODE, aName );
161 str.Replace( wxT(
":" ), wxT(
"_" ) );
164 str.Prepend( wxString( aPrefix ) + wxT(
":" ) );
166 str.Prepend( wxT(
"KI:" ) );
171 str = wxString::Format(
"%s_", aPrefix );
173 for( wxString::const_iterator iter = aStr.begin(); iter != aStr.end(); ++iter )
193 const char* aPrefix )
const
195 return genString( wxString::Format( wxS(
"%s_%s" ),
208 if(
name.empty() && fp )
212 if( fp->
Pads()[ii] == aPad )
220 name = wxString::Format(
"NPTH%zu", ii );
221 else if(
name.empty() )
222 name = wxString::Format(
"PAD%zu", ii );
231 [&](
const wxString& aName )
250 wxString
name = baseName;
253 while( !tryInsert(
name ) )
254 name = wxString::Format(
"%s_%d", baseName, suffix++ );
264 wxString str = wxString::FromCDouble( aVal,
m_sigfig );
267 while( str.EndsWith( wxT(
"00" ) ) )
271 if( str == wxT(
"-0.0" ) )
296 aNode->AddAttribute( aName, aValue );
302 wxXmlNode* xmlHeaderNode =
new wxXmlNode(wxXML_ELEMENT_NODE,
"IPC-2581");
304 addAttribute( xmlHeaderNode,
"xmlns",
"http://webstds.ipc.org/2581");
305 addAttribute( xmlHeaderNode,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
306 addAttribute( xmlHeaderNode,
"xmlns:xsd",
"http://www.w3.org/2001/XMLSchema");
311 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581B1.xsd" );
316 "http://webstds.ipc.org/2581 http://webstds.ipc.org/2581/IPC-2581C.xsd" );
321 return xmlHeaderNode;
333 wxXmlNode* node =
appendNode( contentNode,
"FunctionMode" );
348 contentNode->AddChild( color_node );
352 wxXmlNode* fillNode =
appendNode( contentNode,
"DictionaryFillDesc" );
372 contentNode->AddChild( color_node );
381 wxXmlNode* location_node =
appendNode( aNode,
"Location" );
409 case SHAPE_T::RECTANGLE:
414 case SHAPE_T::CIRCLE:
420 case SHAPE_T::BEZIER:
421 case SHAPE_T::SEGMENT:
426 case SHAPE_T::UNDEFINED:
456 wxXmlNode* color_node =
new wxXmlNode( wxXML_ELEMENT_NODE,
"DictionaryColor" );
460 wxString layer_name = item->GetLayerName();
461 int sub_layer_count = 1;
463 if( layer_name.empty() )
466 layer_name =
genString( layer_name,
"LAYER" );
470 layer_name =
genString( wxString::Format(
"DIELECTRIC_%d", item->GetDielectricLayerId() ),
472 sub_layer_count = item->GetSublayersCount();
479 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
481 wxString sub_layer_name = layer_name;
484 sub_layer_name += wxString::Format(
"_%d", sub_idx );
486 wxXmlNode* node =
appendNode( aContentNode,
"LayerRef" );
492 wxXmlNode* entry_color =
appendNode( color_node,
"EntryColor" );
496 wxString colorName = item->GetColor( sub_idx );
498 if( colorName.StartsWith( wxT(
"#" ) ) )
501 COLOR4D layer_color( colorName );
513 if( fab_color.GetName() == colorName )
531 if( aFill == FILL_T::FILLED_SHAPE )
537 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
543 wxXmlNode* fillDesc_node =
appendNode( aNode,
"FillDesc" );
544 addAttribute( fillDesc_node,
"fillProperty",
"HOLLOW" );
551 wxCHECK_RET( aNode,
"aNode is null" );
556 wxXmlNode* entry_node =
nullptr;
560 size_t hash =
lineHash( aWidth, aDashType );
561 wxString
name = wxString::Format(
"LINE_%zu",
m_line_dict.size() + 1 );
565 wxXmlNode* lineDesc_node =
appendNode( aNode,
"LineDescRef" );
580 wxXmlNode* line_node =
appendNode( entry_node,
"LineDesc" );
586 case LINE_STYLE::DOT:
589 case LINE_STYLE::DASH:
592 case LINE_STYLE::DASHDOT:
595 case LINE_STYLE::DASHDOTDOT:
630 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
635 std::list<VECTOR2I> pts;
643 wxXmlNode* line_node =
nullptr;
650 addXY( line_node, pts.front(),
"startX",
"startY" );
651 addXY( line_node, pts.back(),
"endX",
"endY" );
655 line_node =
appendNode( text_node,
"Polyline" );
656 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
657 addXY( point_node, pts.front() );
659 auto iter = pts.begin();
661 for( ++iter; iter != pts.end(); ++iter )
663 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
664 addXY( point_node, *iter );
679 if( aPt1 == pts.back() )
680 pts.push_back( aPt2 );
681 else if( aPt2 == pts.front() )
682 pts.push_front( aPt1 );
683 else if( aPt1 == pts.front() )
684 pts.push_front( aPt2 );
685 else if( aPt2 == pts.back() )
686 pts.push_back( aPt1 );
690 pts.push_back( aPt1 );
691 pts.push_back( aPt2 );
696 pts.push_back( aPt1 );
697 pts.push_back( aPt2 );
703 if( aPoly.PointCount() < 3 )
706 wxXmlNode* outline_node = appendNode( text_node,
"Outline" );
707 wxXmlNode* poly_node = appendNode( outline_node,
"Polygon" );
710 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
711 wxXmlNode* point_node = appendNode( poly_node,
"PolyBegin" );
712 addXY( point_node, pts.front() );
714 for(
size_t ii = 1; ii < pts.size(); ++ii )
716 wxXmlNode* point_node =
717 appendNode( poly_node,
"PolyStepSegment" );
718 addXY( point_node, pts[ii] );
721 point_node = appendNode( poly_node,
"PolyStepSegment" );
722 addXY( point_node, pts.front() );
727 font->Draw( &callback_gal, aText->GetShownText(
true ), aText->GetTextPos(), attrs,
733 if( text_node->GetChildren() == nullptr )
735 aContentNode->RemoveChild( text_node );
748 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
765 case PAD_SHAPE::CIRCLE:
773 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
774 circle_node->AddAttribute(
"diameter",
779 case PAD_SHAPE::RECTANGLE:
787 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
795 case PAD_SHAPE::OVAL:
803 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
811 case PAD_SHAPE::ROUNDRECT:
819 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
823 roundrect_node->AddAttribute(
"radius",
833 case PAD_SHAPE::CHAMFERED_RECT:
841 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
846 int shorterSide = std::min( pad_size.
x, pad_size.
y );
865 case PAD_SHAPE::TRAPEZOID:
877 int dx = pad_size.
x / 2;
878 int dy = pad_size.
y / 2;
879 int ddx = trap_delta.
x / 2;
880 int ddy = trap_delta.
y / 2;
882 outline.
Append( -dx - ddy, dy + ddx );
883 outline.
Append( dx + ddy, dy - ddx );
884 outline.
Append( dx - ddy, -dy + ddx );
885 outline.
Append( -dx + ddy, -dy - ddx );
899 case PAD_SHAPE::CUSTOM:
913 CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
921 wxLogError(
"Unknown pad type" );
928 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
942 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
949 case SHAPE_T::CIRCLE:
960 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
962 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
980 case SHAPE_T::RECTANGLE:
987 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
994 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1011 width += stroke_width;
1012 height += stroke_width;
1034 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1043 addContourNode( special_node, poly_set, ii, FILL_T::FILLED_SHAPE, 0,
1044 LINE_STYLE::SOLID );
1056 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1058 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1073 case SHAPE_T::BEZIER:
1075 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1079 std::vector<VECTOR2I> points;
1082 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1083 addXY( point_node, points[0] );
1085 for(
size_t i = 1; i < points.size(); i++ )
1087 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1088 addXY( point_node, points[i] );
1100 case SHAPE_T::SEGMENT:
1102 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1104 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1115 case SHAPE_T::UNDEFINED:
1121 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1130 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1151 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1159 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1161 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1164 return logisticNode;
1175 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1177 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1179 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1180 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1181 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1184 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1187 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1189 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1190 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1213 m_refdes =
new std::vector<REFDES>();
1214 m_props =
new std::map<wxString, wxString>();
1225 wxString m_OEMDesignRef;
1229 std::vector<REFDES>* m_refdes;
1230 std::map<wxString, wxString>* m_props;
1233 std::set<std::unique_ptr<struct BOM_ENTRY>,
1234 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1235 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1236 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1237 const std::unique_ptr<struct BOM_ENTRY>& b )
1239 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1244 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1245 fp->SetParentGroup(
nullptr );
1246 fp->SetPosition( {0, 0} );
1248 if( fp->GetLayer() !=
F_Cu )
1249 fp->Flip( fp->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1251 fp->SetOrientation(
ANGLE_0 );
1258 wxLogError(
"Footprint %s not found in dictionary",
1259 fp->GetFPID().GetLibItemName().wx_str() );
1263 auto entry = std::make_unique<struct BOM_ENTRY>();
1269 entry->m_OEMDesignRef = it->second;
1273 wxLogError(
"Footprint %s not found in OEMRef dictionary",
1274 fp->GetFPID().GetLibItemName().wx_str() );
1277 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1279 entry->m_pads = fp->GetPadCount();
1284 entry->m_type =
"DOCUMENT";
1286 entry->m_type =
"ELECTRICAL";
1288 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1291 ( *bom_iter )->m_count++;
1295 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1299 ( *bom_iter )->m_refdes->push_back( refdes );
1303 for(
PCB_FIELD* prop : fp->GetFields() )
1307 if( prop->IsMandatoryField() && !prop->IsValue() )
1310 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1314 if( bom_entries.empty() )
1319 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1320 m_xml_root->InsertChild( bomNode, aEcadNode );
1323 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1327 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1330 for(
const auto& entry : bom_entries )
1332 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1333 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1334 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1335 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1336 addAttribute( bomEntryNode,
"category", entry->m_type );
1338 for(
const REFDES& refdes : *( entry->m_refdes ) )
1340 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1343 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1344 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1347 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1348 addAttribute( characteristicsNode,
"category", entry->m_type );
1350 for(
const auto& prop : *( entry->m_props ) )
1352 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1353 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1354 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1355 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1373 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1384 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1424 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1465 aLayer ==
F_Cu ?
"TOP"
1466 : aLayer ==
B_Cu ?
"BOTTOM"
1482 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1483 std::set<PCB_LAYER_ID> added_layers;
1485 for(
int i = 0; i < stackup.
GetCount(); i++ )
1492 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1494 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1497 if( ly_name.IsEmpty() )
1505 ly_name = wxString::Format(
"DIELECTRIC_%d",
1510 ly_name =
genString( ly_name,
"LAYER" );
1517 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1519 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1543 added_layers.insert( layer );
1544 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1565 for(
PAD*
pad : fp->Pads() )
1567 if(
pad->HasDrilledHole() )
1569 else if(
pad->HasHole() )
1576 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1577 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
1582 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1589 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1590 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
1596 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1605 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1612 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1632 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1639 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1640 xformNode->AddAttribute(
"rotation",
1648 addShape( padNode, *aPad, aLayer );
1652 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1665 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1686 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1693 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1701 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1702 padStackHoleNode->AddAttribute(
"name",
1703 wxString::Format(
"%s%d_%d",
1704 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PTH" :
"NPTH",
1709 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
1724 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1726 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1731 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1734 addShape( padStackPadDefNode, shape );
1738 addShape( padStackPadDefNode, *aPad, layer );
1750 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
1757 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1762 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1765 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
1778 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1782 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1784 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1787 addShape( padStackPadDefNode, shape );
1796 wxXmlNode* polygonNode =
nullptr;
1798 if( aPolygon.empty() || aPolygon[0].PointCount() < 3 )
1804 polygonNode =
appendNode( aParentNode,
"Polygon" );
1805 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
1807 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
1808 addXY( polybeginNode, pts[0] );
1810 for(
size_t ii = 1; ii < pts.size(); ++ii )
1812 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
1813 addXY( polyNode, pts[ii] );
1816 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
1817 addXY( polyendNode, pts[0] );
1821 if( aFillType == FILL_T::NO_FILL )
1828 addLineDesc( polygonNode, aWidth, aDashType,
true );
1832 wxCHECK( aWidth == 0,
false );
1845 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
1847 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
1849 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
1850 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
1852 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
1853 addXY( polybeginNode, hole[0] );
1855 for(
size_t jj = 1; jj < hole.size(); ++jj )
1857 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
1858 addXY( polyNode, hole[jj] );
1861 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
1862 addXY( polyendNode, hole[0] );
1875 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
1882 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
1885 if( !outlineNode->GetChildren() )
1887 aParentNode->RemoveChild( outlineNode );
1899 int aOutline,
FILL_T aFillType,
int aWidth,
1905 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
1910 if( aFillType != FILL_T::NO_FILL )
1915 aParentNode->RemoveChild( contourNode );
1930 wxLogError(
"Failed to get board outline" );
1934 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
1938 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
1939 aStepNode->RemoveChild( profileNode );
1947 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
1948 fp->SetParentGroup(
nullptr );
1949 fp->SetPosition( { 0, 0 } );
1951 if( fp->GetLayer() !=
F_Cu )
1952 fp->Flip( fp->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1954 fp->SetOrientation(
ANGLE_0 );
1958 fp->GetFPID().GetLibItemName().wx_str(),
1962 addAttribute( aContentNode,
"packageRef", iter->second );
1969 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
1970 wxXmlNode* otherSideViewNode =
nullptr;
1976 if( fp->FindPadByNumber(
"1" ) )
1978 else if ( fp->FindPadByNumber(
"A1" ) )
1980 else if ( fp->FindPadByNumber(
"A" ) )
1982 else if ( fp->FindPadByNumber(
"a" ) )
1984 else if ( fp->FindPadByNumber(
"a1" ) )
1986 else if ( fp->FindPadByNumber(
"Anode" ) )
1988 else if ( fp->FindPadByNumber(
"ANODE" ) )
1993 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2003 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2005 LINE_STYLE::SOLID );
2014 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2018 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2020 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2038 if( shape->
GetShape() == SHAPE_T::CIRCLE || shape->
GetShape() == SHAPE_T::RECTANGLE )
2042 elements[item->GetLayer()][is_abs].push_back( item );
2045 auto add_base_node =
2048 wxXmlNode* parent = packageNode;
2053 if( !otherSideViewNode )
2054 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2056 parent = otherSideViewNode;
2062 name =
"SilkScreen";
2063 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2064 name =
"AssemblyDrawing";
2072 auto add_marking_node =
2073 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2075 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2077 return marking_node;
2080 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2081 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2085 if( elements.find( layer ) != elements.end() )
2087 if( elements[layer][
true].size() > 0 )
2088 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2089 else if( elements[layer][
false].size() > 0 )
2090 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2094 for(
auto& [layer, map] : elements )
2096 wxXmlNode* layer_node = add_base_node( layer );
2097 wxXmlNode* marking_node = add_marking_node( layer_node );
2098 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2099 bool update_bbox =
false;
2103 layer_nodes[layer] = layer_node;
2107 for(
auto& [is_abs, vec] : map )
2111 wxXmlNode* output_node =
nullptr;
2114 layer_bbox[layer].Merge( item->GetBoundingBox() );
2117 output_node = add_marking_node( layer_node );
2119 output_node = group_node;
2121 switch( item->Type() )
2127 if(
text->IsKnockout() )
2141 if(
text->IsBorderEnabled() )
2144 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2146 text->GetBorderWidth() );
2167 if( group_node->GetChildren() ==
nullptr )
2169 marking_node->RemoveChild( group_node );
2170 layer_node->RemoveChild( marking_node );
2172 delete marking_node;
2176 for(
auto&[layer, bbox] : layer_bbox )
2178 if( bbox.GetWidth() > 0 )
2180 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2183 std::vector<VECTOR2I> points( 4 );
2184 points[0] = bbox.GetPosition();
2185 points[2] = bbox.GetEnd();
2186 points[1].x = points[0].x;
2187 points[1].y = points[2].y;
2188 points[3].x = points[2].x;
2189 points[3].y = points[0].y;
2191 outline[0].Append( points );
2197 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2199 PAD*
pad = fp->Pads()[ii];
2200 wxXmlNode* pinNode =
appendNode( packageNode,
"Pin" );
2208 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH )
2209 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2210 else if(
pad->IsOnCopperLayer() )
2211 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2213 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2215 if(
pad->HasHole() )
2220 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2222 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2223 xformNode->AddAttribute(
2225 floatVal(
pad->GetFPRelativeOrientation().Normalize().AsDegrees() ) );
2243 std::vector<wxXmlNode*> componentNodes;
2244 std::vector<wxXmlNode*> packageNodes;
2245 std::set<wxString> packageNames;
2247 bool generate_unique =
m_OEMRef.empty();
2251 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2253 wxXmlNode* pkg =
addPackage( componentNode, fp );
2256 packageNodes.push_back( pkg );
2262 if( !generate_unique )
2263 field = fp->GetFieldByName(
m_OEMRef );
2265 if( field && !field->
GetText().empty() )
2271 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2272 fp->GetFPID().GetLibItemName().wx_str(),
2277 wxLogError(
"Duplicate footprint pointers. Please report this bug." );
2284 else if( fp->GetAttributes() &
FP_SMD )
2289 if( fp->GetOrientation() !=
ANGLE_0 || fp->GetLayer() !=
F_Cu )
2291 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2293 if( fp->GetOrientation() !=
ANGLE_0 )
2296 floatVal( fp->GetOrientation().Normalize().AsDegrees() ) );
2299 if( fp->GetLayer() !=
F_Cu )
2303 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2305 componentNodes.push_back( componentNode );
2314 for( wxXmlNode* pkg : packageNodes )
2315 aStepNode->AddChild( pkg );
2317 for( wxXmlNode* cmp : componentNodes )
2318 aStepNode->AddChild( cmp );
2326 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2330 for(
auto& [cmp,
pin] : pin_pair )
2332 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2346 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2350 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2353 [&layers, &elements](
PCB_TRACK* aTrack )
2355 if( aTrack->Type() == PCB_VIA_T )
2357 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2359 for( PCB_LAYER_ID layer : layers )
2361 if( via->FlashLayer( layer ) )
2362 elements[layer][via->GetNetCode()].push_back( via );
2367 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2371 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2372 [ &elements ](
ZONE* zone )
2374 LSEQ zone_layers = zone->GetLayerSet().Seq();
2376 for( PCB_LAYER_ID layer : zone_layers )
2377 elements[layer][zone->GetNetCode()].push_back( zone );
2380 for(
BOARD_ITEM* item : m_board->Drawings() )
2383 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2385 elements[item->GetLayer()][0].push_back( item );
2388 for(
FOOTPRINT* fp : m_board->Footprints() )
2390 for(
PCB_FIELD* field : fp->GetFields() )
2391 elements[field->GetLayer()][0].push_back( field );
2393 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2394 elements[item->GetLayer()][0].push_back( item );
2396 for(
PAD*
pad : fp->Pads() )
2398 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2402 if(
pad->FlashLayer( layer ) )
2403 elements[layer][
pad->GetNetCode()].push_back(
pad );
2410 if( m_progressReporter )
2411 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2413 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2414 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2416 auto process_net = [&] (
int net )
2418 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
2423 std::stable_sort( vec.begin(), vec.end(),
2426 if( a->GetParentFootprint() == b->GetParentFootprint() )
2427 return a->Type() < b->Type();
2429 return a->GetParentFootprint() < b->GetParentFootprint();
2432 generateLayerSetNet( layerNode, layer, vec );
2437 if( m_progressReporter )
2439 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2440 m_board->GetLayerName( layer ),
2441 net->GetNetname() ) );
2442 m_progressReporter->AdvanceProgress();
2445 process_net( net->GetNetCode() );
2448 if( layerNode->GetChildren() ==
nullptr )
2450 aStepNode->RemoveChild( layerNode );
2463 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2464 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2475 wxLogError(
"Failed to find padstack for via" );
2479 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2482 if(
via->GetNetCode() > 0 )
2485 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2486 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2491 addXY( holeNode,
via->GetPosition() );
2500 wxLogError(
"Failed to find padstack for pad" );
2504 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2507 if(
pad->GetNetCode() > 0 )
2510 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2511 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2514 pad->GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
2517 addXY( holeNode,
pad->GetPosition() );
2526 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2527 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2531 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2533 if(
pad->GetNetCode() > 0 )
2536 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2543 std::vector<BOARD_ITEM*>& aItems )
2545 auto it = aItems.begin();
2546 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2547 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2548 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2550 bool has_via =
false;
2551 bool has_pad =
false;
2553 wxXmlNode* padSetNode =
nullptr;
2555 wxXmlNode* viaSetNode =
nullptr;
2557 wxXmlNode* teardropLayerSetNode =
nullptr;
2558 wxXmlNode* teardropFeatureSetNode =
nullptr;
2563 if( item->GetNetCode() > 0 )
2572 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
2573 shape.
SetStart( track->GetStart() );
2574 shape.
SetEnd( track->GetEnd() );
2575 shape.
SetWidth( track->GetWidth() );
2581 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2592 viaSetNode = layerSetNode;
2597 viaSetNode =
appendNode( layerSetNode,
"Set" );
2599 if( track->GetNetCode() > 0 )
2606 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2613 wxXmlNode* zoneFeatureNode = specialNode;
2615 if( zone->IsTeardropArea() &&
m_version >
'B' )
2617 if( !teardropFeatureSetNode )
2619 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
2620 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
2622 if( zone->GetNetCode() > 0 )
2625 genString( zone->GetNetname(),
"NET" ) );
2628 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
2630 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
2633 zoneFeatureNode = teardropFeatureSetNode;
2639 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2640 wxString refDes =
componentName( zone->GetParentFootprint() );
2642 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
2644 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
2648 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
2650 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
2661 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2664 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
2668 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2673 else if( shape->GetShape() == SHAPE_T::CIRCLE
2674 || shape->GetShape() == SHAPE_T::RECTANGLE
2675 || shape->GetShape() == SHAPE_T::POLY )
2677 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2679 if( shape->GetNetCode() > 0 )
2682 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2699 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2701 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2706 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2714 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
2715 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
2717 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
2719 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2725 addText( tempFeature, text_item,
text->GetFontMetrics() );
2743 padSetNode = layerSetNode;
2748 padSetNode =
appendNode( aLayerNode,
"Set" );
2750 if(
pad->GetNetCode() > 0 )
2765 switch( item->Type() )
2770 add_track(
static_cast<PCB_TRACK*
>( item ) );
2778 add_pad(
static_cast<PAD*
>( item ) );
2782 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
2807 if( specialNode->GetChildren() ==
nullptr )
2809 featureSetNode->RemoveChild( specialNode );
2813 if( featureSetNode->GetChildren() ==
nullptr )
2815 layerSetNode->RemoveChild( featureSetNode );
2816 delete featureSetNode;
2819 if( layerSetNode->GetChildren() ==
nullptr )
2821 aLayerNode->RemoveChild( layerSetNode );
2822 delete layerSetNode;
2835 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
2839 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
2842 std::set<wxString> unique_parts;
2843 std::map<wxString,wxString> unique_vendors;
2847 auto [ it, success ] = unique_parts.insert(
name );
2852 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
2856 PCB_FIELD* company[2] = { fp->GetFieldByName(
m_mfg ),
nullptr };
2859 for (
int ii = 0; ii < 2; ++ii )
2865 if( mpn_name.empty() )
2868 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
2872 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
2875 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
2877 wxString
name = wxT(
"UNKNOWN" );
2880 if( !ii && company[ii] )
2888 else if( !ii && !company_name[ii].
empty() )
2890 name = company_name[ii];
2892 else if( ii && !
m_dist.empty() )
2897 auto [vendor_id, inserted] = unique_vendors.emplace(
2899 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
2901 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
2905 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
2921 const std::map<std::string, UTF8>* aProperties )
2928 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
2930 if( it->second ==
"inch" )
2937 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
2938 m_sigfig = std::stoi( it->second );
2940 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
2943 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
2946 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
2947 m_mpn = it->second.wx_str();
2949 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
2950 m_mfg = it->second.wx_str();
2952 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
2953 m_dist = it->second.wx_str();
2955 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
2960 for(
char c =
'a'; c <=
'z'; ++c )
2963 for(
char c =
'A'; c <=
'Z'; ++c )
2966 for(
char c =
'0'; c <=
'9'; ++c )
2970 std::string specialChars =
"_\\-.+><";
2972 for(
char c : specialChars )
3001 double written_bytes = 0.0;
3002 double last_yield = 0.0;
3009 auto update_progress = [&](
size_t aBytes )
3011 written_bytes += aBytes;
3012 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
3017 if( last_yield + 0.01 < percent )
3019 last_yield = percent;
3029 wxLogError(
_(
"Failed to save file to buffer" ) );
3033 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
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
wxString GetMajorMinorPatchVersion()
Get the major, minor and patch version in a string major.minor.patch This is extracted by CMake from ...
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsKnockout() const
FOOTPRINT * GetParentFootprint() const
VECTOR2I GetFPRelativePosition() const
Manage one layer needed to make a physical board.
wxString GetTypeName() const
int GetSublayersCount() const
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, bool aForDrawingSheet=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 LSEQ &aSequence) 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
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
void MergePrimitivesAsPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING flashPTHPads=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
int GetDrillSizeY() const
const VECTOR2I & GetDrillSize() const
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
VECTOR2I GetPosition() const override
int GetDrillSizeX() const
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
int GetChamferPositions(PCB_LAYER_ID aLayer) const
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
VECTOR2I GetSolderPasteMargin(PCB_LAYER_ID aLayer) const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
bool HasDrilledHole() const override
bool HasHole() const override
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) 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)
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
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)
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
virtual int GetWidth() 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 GetWidth() const override
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.
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 constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
static constexpr std::size_t hash_val(const Types &... args)
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
@ 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
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D