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, aSigFig == -1 ?
m_sigfig : aSigFig );
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:
627 wxXmlNode* text_node =
appendNode( aContentNode,
"UserSpecial" );
632 std::list<VECTOR2I> pts;
640 wxXmlNode* line_node =
nullptr;
647 addXY( line_node, pts.front(),
"startX",
"startY" );
648 addXY( line_node, pts.back(),
"endX",
"endY" );
652 line_node =
appendNode( text_node,
"Polyline" );
653 wxXmlNode* point_node =
appendNode( line_node,
"PolyBegin" );
654 addXY( point_node, pts.front() );
656 auto iter = pts.begin();
658 for( ++iter; iter != pts.end(); ++iter )
660 wxXmlNode* point_node =
appendNode( line_node,
"PolyStepSegment" );
661 addXY( point_node, *iter );
676 if( aPt1 == pts.back() )
677 pts.push_back( aPt2 );
678 else if( aPt2 == pts.front() )
679 pts.push_front( aPt1 );
680 else if( aPt1 == pts.front() )
681 pts.push_front( aPt2 );
682 else if( aPt2 == pts.back() )
683 pts.push_back( aPt1 );
687 pts.push_back( aPt1 );
688 pts.push_back( aPt2 );
693 pts.push_back( aPt1 );
694 pts.push_back( aPt2 );
700 if( aPoly.PointCount() < 3 )
703 wxXmlNode* outline_node = appendNode( text_node,
"Outline" );
704 wxXmlNode* poly_node = appendNode( outline_node,
"Polygon" );
707 const std::vector<VECTOR2I>& pts = aPoly.CPoints();
708 wxXmlNode* point_node = appendNode( poly_node,
"PolyBegin" );
709 addXY( point_node, pts.front() );
711 for(
size_t ii = 1; ii < pts.size(); ++ii )
713 wxXmlNode* point_node =
714 appendNode( poly_node,
"PolyStepSegment" );
715 addXY( point_node, pts[ii] );
718 point_node = appendNode( poly_node,
"PolyStepSegment" );
719 addXY( point_node, pts.front() );
724 font->Draw( &callback_gal, aText->GetShownText(
true ), aText->GetTextPos(), attrs,
730 if( text_node->GetChildren() == nullptr )
732 aContentNode->RemoveChild( text_node );
745 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
762 case PAD_SHAPE::CIRCLE:
770 wxXmlNode* circle_node =
appendNode( entry_node,
"Circle" );
771 circle_node->AddAttribute(
"diameter",
776 case PAD_SHAPE::RECTANGLE:
784 wxXmlNode* rect_node =
appendNode( entry_node,
"RectCenter" );
792 case PAD_SHAPE::OVAL:
800 wxXmlNode* oval_node =
appendNode( entry_node,
"Oval" );
808 case PAD_SHAPE::ROUNDRECT:
816 wxXmlNode* roundrect_node =
appendNode( entry_node,
"RectRound" );
820 roundrect_node->AddAttribute(
"radius",
830 case PAD_SHAPE::CHAMFERED_RECT:
838 wxXmlNode* chamfered_node =
appendNode( entry_node,
"RectCham" );
843 int shorterSide = std::min( pad_size.
x, pad_size.
y );
862 case PAD_SHAPE::TRAPEZOID:
874 int dx = pad_size.
x / 2;
875 int dy = pad_size.
y / 2;
876 int ddx = trap_delta.
x / 2;
877 int ddy = trap_delta.
y / 2;
879 outline.
Append( -dx - ddy, dy + ddx );
880 outline.
Append( dx + ddy, dy - ddx );
881 outline.
Append( dx - ddy, -dy + ddx );
882 outline.
Append( -dx + ddy, -dy - ddx );
896 case PAD_SHAPE::CUSTOM:
910 CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError );
917 wxLogError(
"Unknown pad type" );
924 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
938 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
945 case SHAPE_T::CIRCLE:
956 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
958 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
976 case SHAPE_T::RECTANGLE:
983 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
990 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1007 width += stroke_width;
1008 height += stroke_width;
1030 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1039 addContourNode( special_node, poly_set, ii, FILL_T::FILLED_SHAPE, 0,
1040 LINE_STYLE::SOLID );
1052 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1054 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1069 case SHAPE_T::BEZIER:
1071 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1075 std::vector<VECTOR2I> points;
1078 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1079 addXY( point_node, points[0] );
1081 for(
size_t i = 1; i < points.size(); i++ )
1083 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1084 addXY( point_node, points[i] );
1096 case SHAPE_T::SEGMENT:
1098 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1100 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1111 case SHAPE_T::UNDEFINED:
1117 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1126 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1147 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1155 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1157 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1160 return logisticNode;
1171 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1173 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1175 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1176 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1177 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1180 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1183 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1185 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1186 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1209 m_refdes =
new std::vector<REFDES>();
1210 m_props =
new std::map<wxString, wxString>();
1221 wxString m_OEMDesignRef;
1225 std::vector<REFDES>* m_refdes;
1226 std::map<wxString, wxString>* m_props;
1229 std::set<std::unique_ptr<struct BOM_ENTRY>,
1230 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1231 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1232 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1233 const std::unique_ptr<struct BOM_ENTRY>& b )
1235 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1240 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1241 fp->SetParentGroup(
nullptr );
1242 fp->SetPosition( {0, 0} );
1243 fp->SetOrientation(
ANGLE_0 );
1250 wxLogError(
"Footprint %s not found in dictionary",
1251 fp->GetFPID().GetLibItemName().wx_str() );
1255 auto entry = std::make_unique<struct BOM_ENTRY>();
1261 entry->m_OEMDesignRef = it->second;
1265 wxLogError(
"Footprint %s not found in OEMRef dictionary",
1266 fp->GetFPID().GetLibItemName().wx_str() );
1269 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1271 entry->m_pads = fp->GetPadCount();
1276 entry->m_type =
"DOCUMENT";
1278 entry->m_type =
"ELECTRICAL";
1280 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1283 ( *bom_iter )->m_count++;
1287 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1291 ( *bom_iter )->m_refdes->push_back( refdes );
1295 for(
PCB_FIELD* prop : fp->GetFields() )
1299 if( prop->IsMandatory() && !prop->IsValue() )
1302 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1306 if( bom_entries.empty() )
1311 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1312 m_xml_root->InsertChild( bomNode, aEcadNode );
1315 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1319 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1322 for(
const auto& entry : bom_entries )
1324 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1325 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1326 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1327 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1328 addAttribute( bomEntryNode,
"category", entry->m_type );
1330 for(
const REFDES& refdes : *( entry->m_refdes ) )
1332 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1335 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1336 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1339 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1340 addAttribute( characteristicsNode,
"category", entry->m_type );
1342 for(
const auto& prop : *( entry->m_props ) )
1344 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1345 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1346 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1347 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1365 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1381 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1382 std::set<PCB_LAYER_ID> added_layers;
1384 for(
int i = 0; i < stackup.
GetCount(); i++ )
1388 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1392 if( ly_name.IsEmpty() )
1401 if( sublayer_id > 0 )
1402 ly_name += wxString::Format(
"_%d", sublayer_id );
1406 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1408 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1410 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1412 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1414 switch ( stackup_item->
GetType() )
1419 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1421 propertyNode =
appendNode( conductorNode,
"Property" );
1422 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1423 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1429 propertyNode =
appendNode( generalNode,
"Property" );
1430 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1432 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1433 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1434 propertyNode =
appendNode( dielectricNode,
"Property" );
1437 dielectricNode =
appendNode( specNode,
"Dielectric" );
1438 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1439 propertyNode =
appendNode( dielectricNode,
"Property" );
1446 propertyNode =
appendNode( generalNode,
"Property" );
1447 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1449 propertyNode =
appendNode( generalNode,
"Property" );
1450 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1455 propertyNode =
appendNode( generalNode,
"Property" );
1456 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1458 propertyNode =
appendNode( generalNode,
"Property" );
1459 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1472 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1514 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1555 aLayer ==
F_Cu ?
"TOP"
1556 : aLayer ==
B_Cu ?
"BOTTOM"
1571 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1572 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1579 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1581 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1582 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1587 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1588 std::set<PCB_LAYER_ID> added_layers;
1590 for(
int i = 0; i < stackup.
GetCount(); i++ )
1594 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1597 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1600 if( ly_name.IsEmpty() )
1609 if( sublayer_id > 0 )
1610 ly_name += wxString::Format(
"_%d", sublayer_id );
1614 ly_name =
genString( ly_name,
"LAYER" );
1616 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1620 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", i ) );
1622 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1623 addAttribute( specLayerNode,
"id", wxString::Format(
"SPEC_%s", ly_name ) );
1636 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1637 std::set<PCB_LAYER_ID> added_layers;
1639 for(
int i = 0; i < stackup.
GetCount(); i++ )
1646 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1648 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1651 if( ly_name.IsEmpty() )
1661 if( sublayer_id > 0 )
1662 ly_name += wxString::Format(
"_%d", sublayer_id );
1666 ly_name =
genString( ly_name,
"LAYER" );
1673 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1675 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1699 added_layers.insert( layer );
1700 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1721 for(
PAD*
pad : fp->Pads() )
1723 if(
pad->HasDrilledHole() )
1725 else if(
pad->HasHole() )
1732 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1733 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
1738 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1745 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1746 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
1752 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1761 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1768 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1788 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1795 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1802 addShape( padNode, *aPad, aLayer );
1806 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1819 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1840 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1847 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1861 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1862 padStackHoleNode->AddAttribute(
"name",
1863 wxString::Format(
"%s%d_%d",
1864 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PTH" :
"NPTH",
1869 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
1884 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1886 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1891 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1894 addShape( padStackPadDefNode, shape );
1898 addShape( padStackPadDefNode, *aPad, layer );
1910 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
1917 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1922 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1925 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
1938 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1942 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1944 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1947 addShape( padStackPadDefNode, shape );
1956 wxXmlNode* polygonNode =
nullptr;
1964 polygonNode =
appendNode( aParentNode,
"Polygon" );
1965 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
1967 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
1968 addXY( polybeginNode, pts[0] );
1970 for(
size_t ii = 1; ii < pts.size(); ++ii )
1972 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
1973 addXY( polyNode, pts[ii] );
1976 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
1977 addXY( polyendNode, pts[0] );
1981 if( aFillType == FILL_T::NO_FILL )
1988 addLineDesc( polygonNode, aWidth, aDashType,
true );
1992 wxCHECK( aWidth == 0,
false );
2005 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2007 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2009 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2010 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2012 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2013 addXY( polybeginNode, hole[0] );
2015 for(
size_t jj = 1; jj < hole.size(); ++jj )
2017 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2018 addXY( polyNode, hole[jj] );
2021 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2022 addXY( polyendNode, hole[0] );
2035 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2055 outline = &bbox_outline;
2060 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2062 if( !outlineNode->GetChildren() )
2064 aParentNode->RemoveChild( outlineNode );
2076 int aOutline,
FILL_T aFillType,
int aWidth,
2082 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2087 if( aFillType != FILL_T::NO_FILL )
2092 aParentNode->RemoveChild( contourNode );
2107 wxLogError(
"Failed to get board outline" );
2111 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2115 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2116 aStepNode->RemoveChild( profileNode );
2124 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2125 fp->SetParentGroup(
nullptr );
2126 fp->SetPosition( { 0, 0 } );
2127 fp->SetOrientation(
ANGLE_0 );
2131 fp->GetFPID().GetLibItemName().wx_str(),
2135 addAttribute( aContentNode,
"packageRef", iter->second );
2142 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2143 wxXmlNode* otherSideViewNode =
nullptr;
2149 if( fp->FindPadByNumber(
"1" ) )
2151 else if ( fp->FindPadByNumber(
"A1" ) )
2153 else if ( fp->FindPadByNumber(
"A" ) )
2155 else if ( fp->FindPadByNumber(
"a" ) )
2157 else if ( fp->FindPadByNumber(
"a1" ) )
2159 else if ( fp->FindPadByNumber(
"Anode" ) )
2161 else if ( fp->FindPadByNumber(
"ANODE" ) )
2166 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2176 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2178 LINE_STYLE::SOLID );
2187 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2191 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2193 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2211 if( shape->
GetShape() == SHAPE_T::CIRCLE || shape->
GetShape() == SHAPE_T::RECTANGLE )
2215 elements[item->GetLayer()][is_abs].push_back( item );
2218 auto add_base_node =
2221 wxXmlNode* parent = packageNode;
2226 if( !otherSideViewNode )
2227 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2229 parent = otherSideViewNode;
2235 name =
"SilkScreen";
2236 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2237 name =
"AssemblyDrawing";
2245 auto add_marking_node =
2246 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2248 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2250 return marking_node;
2253 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2254 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2258 if( elements.find( layer ) != elements.end() )
2260 if( elements[layer][
true].size() > 0 )
2261 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2262 else if( elements[layer][
false].size() > 0 )
2263 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2267 for(
auto& [layer, map] : elements )
2269 wxXmlNode* layer_node = add_base_node( layer );
2270 wxXmlNode* marking_node = add_marking_node( layer_node );
2271 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2272 bool update_bbox =
false;
2276 layer_nodes[layer] = layer_node;
2280 for(
auto& [is_abs, vec] : map )
2284 wxXmlNode* output_node =
nullptr;
2287 layer_bbox[layer].Merge( item->GetBoundingBox() );
2290 output_node = add_marking_node( layer_node );
2292 output_node = group_node;
2294 switch( item->Type() )
2300 if(
text->IsKnockout() )
2314 if(
text->IsBorderEnabled() )
2317 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2319 text->GetBorderWidth() );
2340 if( group_node->GetChildren() ==
nullptr )
2342 marking_node->RemoveChild( group_node );
2343 layer_node->RemoveChild( marking_node );
2345 delete marking_node;
2349 for(
auto&[layer, bbox] : layer_bbox )
2351 if( bbox.GetWidth() > 0 )
2353 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2356 std::vector<VECTOR2I> points( 4 );
2357 points[0] = bbox.GetPosition();
2358 points[2] = bbox.GetEnd();
2359 points[1].x = points[0].x;
2360 points[1].y = points[2].y;
2361 points[3].x = points[2].x;
2362 points[3].y = points[0].y;
2364 outline.
Append( points );
2370 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2372 PAD*
pad = fp->Pads()[ii];
2373 wxXmlNode* pinNode =
appendNode( packageNode,
"Pin" );
2381 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH )
2382 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2383 else if(
pad->IsOnCopperLayer() )
2384 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2386 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2388 if(
pad->HasHole() )
2393 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2395 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2396 EDA_ANGLE pad_angle =
pad->GetFPRelativeOrientation().Normalize();
2398 if( fp->IsFlipped() )
2420 std::vector<wxXmlNode*> componentNodes;
2421 std::vector<wxXmlNode*> packageNodes;
2422 std::set<wxString> packageNames;
2424 bool generate_unique =
m_OEMRef.empty();
2428 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2430 wxXmlNode* pkg =
addPackage( componentNode, fp );
2433 packageNodes.push_back( pkg );
2439 if( !generate_unique )
2440 field = fp->GetFieldByName(
m_OEMRef );
2442 if( field && !field->
GetText().empty() )
2448 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2449 fp->GetFPID().GetLibItemName().wx_str(),
2454 wxLogError(
"Duplicate footprint pointers. Please report this bug." );
2461 else if( fp->GetAttributes() &
FP_SMD )
2466 if( fp->GetOrientation() !=
ANGLE_0 || fp->IsFlipped() )
2468 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2472 if( fp->IsFlipped() )
2478 if( fp->IsFlipped() )
2482 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2484 componentNodes.push_back( componentNode );
2493 for( wxXmlNode* pkg : packageNodes )
2494 aStepNode->AddChild( pkg );
2496 for( wxXmlNode* cmp : componentNodes )
2497 aStepNode->AddChild( cmp );
2505 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2509 for(
auto& [cmp,
pin] : pin_pair )
2511 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2525 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2529 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2532 [&layers, &elements](
PCB_TRACK* aTrack )
2534 if( aTrack->Type() == PCB_VIA_T )
2536 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2538 for( PCB_LAYER_ID layer : layers )
2540 if( via->FlashLayer( layer ) )
2541 elements[layer][via->GetNetCode()].push_back( via );
2546 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2550 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2551 [ &elements ](
ZONE* zone )
2553 LSEQ zone_layers = zone->GetLayerSet().Seq();
2555 for( PCB_LAYER_ID layer : zone_layers )
2556 elements[layer][zone->GetNetCode()].push_back( zone );
2559 for(
BOARD_ITEM* item : m_board->Drawings() )
2562 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2564 elements[item->GetLayer()][0].push_back( item );
2567 for(
FOOTPRINT* fp : m_board->Footprints() )
2569 for(
PCB_FIELD* field : fp->GetFields() )
2570 elements[field->GetLayer()][0].push_back( field );
2572 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2573 elements[item->GetLayer()][0].push_back( item );
2575 for(
PAD*
pad : fp->Pads() )
2577 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2581 if(
pad->FlashLayer( layer ) )
2582 elements[layer][
pad->GetNetCode()].push_back(
pad );
2589 if( m_progressReporter )
2590 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2592 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2593 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2595 auto process_net = [&] (
int net )
2597 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
2602 std::stable_sort( vec.begin(), vec.end(),
2605 if( a->GetParentFootprint() == b->GetParentFootprint() )
2606 return a->Type() < b->Type();
2608 return a->GetParentFootprint() < b->GetParentFootprint();
2611 generateLayerSetNet( layerNode, layer, vec );
2616 if( m_progressReporter )
2618 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2619 m_board->GetLayerName( layer ),
2620 net->GetNetname() ) );
2621 m_progressReporter->AdvanceProgress();
2624 process_net( net->GetNetCode() );
2627 if( layerNode->GetChildren() ==
nullptr )
2629 aStepNode->RemoveChild( layerNode );
2642 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2643 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2654 wxLogError(
"Failed to find padstack for via" );
2658 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2661 if(
via->GetNetCode() > 0 )
2664 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2665 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2670 addXY( holeNode,
via->GetPosition() );
2679 wxLogError(
"Failed to find padstack for pad" );
2683 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2686 if(
pad->GetNetCode() > 0 )
2689 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2690 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2693 pad->GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
2696 addXY( holeNode,
pad->GetPosition() );
2705 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2706 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2710 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2712 if(
pad->GetNetCode() > 0 )
2715 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2722 std::vector<BOARD_ITEM*>& aItems )
2724 auto it = aItems.begin();
2725 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2726 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2727 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2729 bool has_via =
false;
2730 bool has_pad =
false;
2732 wxXmlNode* padSetNode =
nullptr;
2734 wxXmlNode* viaSetNode =
nullptr;
2736 wxXmlNode* teardropLayerSetNode =
nullptr;
2737 wxXmlNode* teardropFeatureSetNode =
nullptr;
2742 if( item->GetNetCode() > 0 )
2751 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
2752 shape.
SetStart( track->GetStart() );
2753 shape.
SetEnd( track->GetEnd() );
2754 shape.
SetWidth( track->GetWidth() );
2760 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2771 viaSetNode = layerSetNode;
2776 viaSetNode =
appendNode( layerSetNode,
"Set" );
2778 if( track->GetNetCode() > 0 )
2785 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2792 wxXmlNode* zoneFeatureNode = specialNode;
2794 if( zone->IsTeardropArea() &&
m_version >
'B' )
2796 if( !teardropFeatureSetNode )
2798 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
2799 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
2801 if( zone->GetNetCode() > 0 )
2804 genString( zone->GetNetname(),
"NET" ) );
2807 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
2809 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
2812 zoneFeatureNode = teardropFeatureSetNode;
2818 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2819 wxString refDes =
componentName( zone->GetParentFootprint() );
2821 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
2823 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
2827 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
2829 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
2840 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2843 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
2847 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2852 else if( shape->GetShape() == SHAPE_T::CIRCLE
2853 || shape->GetShape() == SHAPE_T::RECTANGLE
2854 || shape->GetShape() == SHAPE_T::POLY )
2856 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2858 if( shape->GetNetCode() > 0 )
2861 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2878 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2880 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2885 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2893 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
2894 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
2896 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
2898 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2904 addText( tempFeature, text_item,
text->GetFontMetrics() );
2922 padSetNode = layerSetNode;
2927 padSetNode =
appendNode( aLayerNode,
"Set" );
2929 if(
pad->GetNetCode() > 0 )
2944 switch( item->Type() )
2949 add_track(
static_cast<PCB_TRACK*
>( item ) );
2957 add_pad(
static_cast<PAD*
>( item ) );
2961 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
2986 if( specialNode->GetChildren() ==
nullptr )
2988 featureSetNode->RemoveChild( specialNode );
2992 if( featureSetNode->GetChildren() ==
nullptr )
2994 layerSetNode->RemoveChild( featureSetNode );
2995 delete featureSetNode;
2998 if( layerSetNode->GetChildren() ==
nullptr )
3000 aLayerNode->RemoveChild( layerSetNode );
3001 delete layerSetNode;
3014 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3018 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3021 std::set<wxString> unique_parts;
3022 std::map<wxString,wxString> unique_vendors;
3026 auto [ it, success ] = unique_parts.insert(
name );
3031 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3035 PCB_FIELD* company[2] = { fp->GetFieldByName(
m_mfg ),
nullptr };
3038 for (
int ii = 0; ii < 2; ++ii )
3044 if( mpn_name.empty() )
3047 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3051 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3054 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3056 wxString
name = wxT(
"UNKNOWN" );
3059 if( !ii && company[ii] )
3067 else if( !ii && !company_name[ii].
empty() )
3069 name = company_name[ii];
3071 else if( ii && !
m_dist.empty() )
3076 auto [vendor_id, inserted] = unique_vendors.emplace(
3078 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3080 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3084 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3100 const std::map<std::string, UTF8>* aProperties )
3107 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3109 if( it->second ==
"inch" )
3116 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3117 m_sigfig = std::stoi( it->second );
3119 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3122 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3125 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3126 m_mpn = it->second.wx_str();
3128 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3129 m_mfg = it->second.wx_str();
3131 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3132 m_dist = it->second.wx_str();
3134 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3139 for(
char c =
'a'; c <=
'z'; ++c )
3142 for(
char c =
'A'; c <=
'Z'; ++c )
3145 for(
char c =
'0'; c <=
'9'; ++c )
3149 std::string specialChars =
"_\\-.+><";
3151 for(
char c : specialChars )
3180 double written_bytes = 0.0;
3181 double last_yield = 0.0;
3188 auto update_progress = [&](
size_t aBytes )
3190 written_bytes += aBytes;
3191 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
3196 if( last_yield + 0.01 < percent )
3198 last_yield = percent;
3208 wxLogError(
_(
"Failed to save file to buffer" ) );
3212 size_t size = out_stream.GetSize();
constexpr int ARC_HIGH_DEF
constexpr double PCB_IU_PER_MM
Pcbnew IU is 1 nanometer.
bool IsPrmSpecified(const wxString &aPrmValue)
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERMASK
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
wxString GetMajorMinorPatchVersion()
Get the major, minor and patch version in a string major.minor.patch This is extracted by CMake from ...
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Container for design settings for a BOARD object.
BOARD_STACKUP & GetStackupDescriptor()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsKnockout() const
FOOTPRINT * GetParentFootprint() const
VECTOR2I GetFPRelativePosition() const
Manage one layer needed to make a physical board.
wxString GetTypeName() const
int GetSublayersCount() const
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString GetColor(int aDielectricSubLayer=0) const
wxString GetLayerName() const
PCB_LAYER_ID GetBrdLayerId() const
int GetThickness(int aDielectricSubLayer=0) const
BOARD_STACKUP_ITEM_TYPE GetType() const
wxString GetMaterial(int aDielectricSubLayer=0) const
int GetDielectricLayerId() const
double GetLossTangent(int aDielectricSubLayer=0) const
Manage layers needed to make a physical board.
const std::vector< BOARD_STACKUP_ITEM * > & GetList() const
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
int BuildBoardThicknessFromStackup() const
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
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() 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)
wxString floatVal(double aVal, int aSigFig=-1) const
void generateLayerSetDrill(wxXmlNode *aStepNode)
wxString genLayerString(PCB_LAYER_ID aLayer, const char *aPrefix) const
wxXmlNode * generateContentSection()
Creates the Content section of the XML file.
wxXmlNode * appendNode(wxXmlNode *aParent, const wxString &aName)
void 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 generateStackup(wxXmlNode *aCadLayerNode)
bool addPolygonNode(wxXmlNode *aParentNode, const SHAPE_LINE_CHAIN &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE, int aWidth=0, LINE_STYLE aDashType=LINE_STYLE::SOLID)
void generateLayerSetNet(wxXmlNode *aLayerNode, PCB_LAYER_ID aLayer, std::vector< BOARD_ITEM * > &aItems)
bool isValidLayerFor2581(PCB_LAYER_ID aLayer)
void insertNodeAfter(wxXmlNode *aPrev, wxXmlNode *aNode)
void generateCadLayers(wxXmlNode *aCadLayerNode)
std::vector< wxXmlNode * > m_padstacks
wxString pinName(const PAD *aPad) const
void generateCadSpecs(wxXmlNode *aCadLayerNode)
void addVia(wxXmlNode *aContentNode, const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
void addSlotCavity(wxXmlNode *aContentNode, const PAD &aPad, const wxString &aName)
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
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)
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.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
void Fracture()
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.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
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 constexpr EDA_ANGLE ANGLE_180
static const wxChar traceIpc2581[]
This program source code file is part of KiCad, a free EDA CAD application.
static constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
static constexpr std::size_t hash_val(const Types &... args)
size_t hash_fp_item(const EDA_ITEM *aItem, int aFlags)
Calculate hash of an EDA_ITEM.
Hashing functions for EDA_ITEMs.
@ REL_COORD
Use coordinates relative to the parent object.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
bool IsValidLayer(int aLayerId)
Test whether a given integer is a valid layer index, i.e.
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