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:
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 );
920 wxLogError(
"Unknown pad type" );
927 wxXmlNode* shape_node =
appendNode( aContentNode,
"StandardPrimitiveRef" );
941 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
948 case SHAPE_T::CIRCLE:
959 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
961 wxXmlNode* circle_node =
appendNode( special_node,
"Circle" );
979 case SHAPE_T::RECTANGLE:
986 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
993 wxXmlNode* rect_node =
appendNode( special_node,
"RectRound" );
1010 width += stroke_width;
1011 height += stroke_width;
1033 wxXmlNode* special_node =
appendNode( entry_node,
"UserSpecial" );
1042 addContourNode( special_node, poly_set, ii, FILL_T::FILLED_SHAPE, 0,
1043 LINE_STYLE::SOLID );
1055 wxXmlNode* arc_node =
appendNode( aContentNode,
"Arc" );
1057 addXY( arc_node, aShape.
GetEnd(),
"endX",
"endY" );
1072 case SHAPE_T::BEZIER:
1074 wxXmlNode* polyline_node =
appendNode( aContentNode,
"Polyline" );
1078 std::vector<VECTOR2I> points;
1081 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyBegin" );
1082 addXY( point_node, points[0] );
1084 for(
size_t i = 1; i < points.size(); i++ )
1086 wxXmlNode* point_node =
appendNode( polyline_node,
"PolyStepSegment" );
1087 addXY( point_node, points[i] );
1099 case SHAPE_T::SEGMENT:
1101 wxXmlNode* line_node =
appendNode( aContentNode,
"Line" );
1103 addXY( line_node, aShape.
GetEnd(),
"endX",
"endY" );
1114 case SHAPE_T::UNDEFINED:
1120 wxXmlNode* shape_node =
appendNode( aContentNode,
"UserPrimitiveRef" );
1129 wxXmlNode* slotNode =
appendNode( aNode,
"SlotCavity" );
1150 wxXmlNode* roleNode =
appendNode( logisticNode,
"Role" );
1158 wxXmlNode* personNode =
appendNode( logisticNode,
"Person" );
1160 addAttribute( personNode,
"enterpriseRef",
"UNKNOWN" );
1163 return logisticNode;
1174 addAttribute( historyNode,
"origination", wxDateTime::Now().FormatISOCombined() );
1176 addAttribute( historyNode,
"lastChange", wxDateTime::Now().FormatISOCombined() );
1178 wxXmlNode* fileRevisionNode =
appendNode( historyNode,
"FileRevision" );
1179 addAttribute( fileRevisionNode,
"fileRevisionId",
"1" );
1180 addAttribute( fileRevisionNode,
"comment",
"NO COMMENT" );
1183 wxXmlNode* softwarePackageNode =
appendNode( fileRevisionNode,
"SoftwarePackage" );
1186 addAttribute( softwarePackageNode,
"vendor",
"KiCad EDA" );
1188 wxXmlNode* certificationNode =
appendNode( softwarePackageNode,
"Certification" );
1189 addAttribute( certificationNode,
"certificationStatus",
"SELFTEST" );
1212 m_refdes =
new std::vector<REFDES>();
1213 m_props =
new std::map<wxString, wxString>();
1224 wxString m_OEMDesignRef;
1228 std::vector<REFDES>* m_refdes;
1229 std::map<wxString, wxString>* m_props;
1232 std::set<std::unique_ptr<struct BOM_ENTRY>,
1233 std::function<bool(
const std::unique_ptr<struct BOM_ENTRY>&,
1234 const std::unique_ptr<struct BOM_ENTRY>& )>> bom_entries(
1235 [](
const std::unique_ptr<struct BOM_ENTRY>& a,
1236 const std::unique_ptr<struct BOM_ENTRY>& b )
1238 return a->m_OEMDesignRef < b->m_OEMDesignRef;
1243 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( fp_it->Clone() ) );
1244 fp->SetParentGroup(
nullptr );
1245 fp->SetPosition( {0, 0} );
1247 if( fp->GetLayer() !=
F_Cu )
1248 fp->Flip( fp->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
1250 fp->SetOrientation(
ANGLE_0 );
1257 wxLogError(
"Footprint %s not found in dictionary",
1258 fp->GetFPID().GetLibItemName().wx_str() );
1262 auto entry = std::make_unique<struct BOM_ENTRY>();
1268 entry->m_OEMDesignRef = it->second;
1272 wxLogError(
"Footprint %s not found in OEMRef dictionary",
1273 fp->GetFPID().GetLibItemName().wx_str() );
1276 entry->m_OEMDesignRef =
genString( entry->m_OEMDesignRef,
"REF" );
1278 entry->m_pads = fp->GetPadCount();
1283 entry->m_type =
"DOCUMENT";
1285 entry->m_type =
"ELECTRICAL";
1287 auto[ bom_iter, inserted ] = bom_entries.insert( std::move( entry ) );
1290 ( *bom_iter )->m_count++;
1294 refdes.m_pkg = fp->GetFPID().GetLibItemName().wx_str();
1298 ( *bom_iter )->m_refdes->push_back( refdes );
1302 for(
PCB_FIELD* prop : fp->GetFields() )
1306 if( prop->IsMandatoryField() && !prop->IsValue() )
1309 ( *bom_iter )->m_props->emplace( prop->GetName(), prop->GetText() );
1313 if( bom_entries.empty() )
1318 wxXmlNode* bomNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Bom" );
1319 m_xml_root->InsertChild( bomNode, aEcadNode );
1322 wxXmlNode* bomHeaderNode =
appendNode( bomNode,
"BomHeader" );
1326 wxXmlNode* stepRefNode =
appendNode( bomHeaderNode,
"StepRef" );
1329 for(
const auto& entry : bom_entries )
1331 wxXmlNode* bomEntryNode =
appendNode( bomNode,
"BomItem" );
1332 addAttribute( bomEntryNode,
"OEMDesignNumberRef", entry->m_OEMDesignRef );
1333 addAttribute( bomEntryNode,
"quantity", wxString::Format(
"%d", entry->m_count ) );
1334 addAttribute( bomEntryNode,
"pinCount", wxString::Format(
"%d", entry->m_pads ) );
1335 addAttribute( bomEntryNode,
"category", entry->m_type );
1337 for(
const REFDES& refdes : *( entry->m_refdes ) )
1339 wxXmlNode* refdesNode =
appendNode( bomEntryNode,
"RefDes" );
1342 addAttribute( refdesNode,
"populate", refdes.m_populate ?
"true" :
"false" );
1343 addAttribute( refdesNode,
"layerRef", refdes.m_layer );
1346 wxXmlNode* characteristicsNode =
appendNode( bomEntryNode,
"Characteristics" );
1347 addAttribute( characteristicsNode,
"category", entry->m_type );
1349 for(
const auto& prop : *( entry->m_props ) )
1351 wxXmlNode* textualDefNode =
appendNode( characteristicsNode,
"Textual" );
1352 addAttribute( textualDefNode,
"definitionSource",
"KICAD" );
1353 addAttribute( textualDefNode,
"textualCharacteristicName", prop.first );
1354 addAttribute( textualDefNode,
"textualCharacteristicValue", prop.second );
1372 wxXmlNode* cadDataNode =
appendNode( ecadNode,
"CadData" );
1388 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1389 std::set<PCB_LAYER_ID> added_layers;
1391 for(
int i = 0; i < stackup.
GetCount(); i++ )
1395 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1399 if( ly_name.IsEmpty() )
1408 if( sublayer_id > 0 )
1409 ly_name += wxString::Format(
"_%d", sublayer_id );
1413 ly_name =
genString( ly_name,
"SPEC_LAYER" );
1415 wxXmlNode* specNode =
appendNode( aCadLayerNode,
"Spec" );
1417 wxXmlNode* generalNode =
appendNode( specNode,
"General" );
1419 wxXmlNode* propertyNode =
appendNode( generalNode,
"Property" );
1421 switch ( stackup_item->
GetType() )
1426 wxXmlNode* conductorNode =
appendNode( specNode,
"Conductor" );
1428 propertyNode =
appendNode( conductorNode,
"Property" );
1429 addAttribute( propertyNode,
"unit", wxT(
"SIEMENS/M" ) );
1430 addAttribute( propertyNode,
"value", wxT(
"5.959E7" ) );
1436 propertyNode =
appendNode( generalNode,
"Property" );
1437 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1439 wxXmlNode* dielectricNode =
appendNode( specNode,
"Dielectric" );
1440 addAttribute( dielectricNode,
"type",
"DIELECTRIC_CONSTANT" );
1441 propertyNode =
appendNode( dielectricNode,
"Property" );
1444 dielectricNode =
appendNode( specNode,
"Dielectric" );
1445 addAttribute( dielectricNode,
"type",
"LOSS_TANGENT" );
1446 propertyNode =
appendNode( dielectricNode,
"Property" );
1453 propertyNode =
appendNode( generalNode,
"Property" );
1454 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1456 propertyNode =
appendNode( generalNode,
"Property" );
1457 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1462 propertyNode =
appendNode( generalNode,
"Property" );
1463 addAttribute( propertyNode,
"text", wxString::Format(
"Color : %s",
1465 propertyNode =
appendNode( generalNode,
"Property" );
1466 addAttribute( propertyNode,
"text", wxString::Format(
"Type : %s",
1479 wxXmlNode* cadHeaderNode =
appendNode( aEcadNode,
"CadHeader" );
1521 addAttribute( aNode,
"layerFunction",
"BOARD_OUTLINE" );
1562 aLayer ==
F_Cu ?
"TOP"
1563 : aLayer ==
B_Cu ?
"BOTTOM"
1578 wxXmlNode* stackupNode =
appendNode( aCadLayerNode,
"Stackup" );
1579 addAttribute( stackupNode,
"name",
"Primary_Stackup" );
1586 addAttribute( stackupNode,
"stackupStatus",
"PROPOSED" );
1588 wxXmlNode* stackupGroup =
appendNode( stackupNode,
"StackupGroup" );
1589 addAttribute( stackupGroup,
"name",
"Primary_Stackup_Group" );
1594 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1595 std::set<PCB_LAYER_ID> added_layers;
1597 for(
int i = 0; i < stackup.
GetCount(); i++ )
1601 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1604 wxXmlNode* stackupLayer =
appendNode( stackupGroup,
"StackupLayer" );
1607 if( ly_name.IsEmpty() )
1616 if( sublayer_id > 0 )
1617 ly_name += wxString::Format(
"_%d", sublayer_id );
1621 ly_name =
genString( ly_name,
"LAYER" );
1623 addAttribute( stackupLayer,
"layerOrGroupRef", ly_name );
1627 addAttribute( stackupLayer,
"sequence", wxString::Format(
"%d", i ) );
1629 wxXmlNode* specLayerNode =
appendNode( stackupLayer,
"SpecRef" );
1630 addAttribute( specLayerNode,
"id", wxString::Format(
"SPEC_%s", ly_name ) );
1643 std::vector<BOARD_STACKUP_ITEM*> layers = stackup.
GetList();
1644 std::set<PCB_LAYER_ID> added_layers;
1646 for(
int i = 0; i < stackup.
GetCount(); i++ )
1653 for(
int sublayer_id = 0; sublayer_id < stackup_item->
GetSublayersCount(); sublayer_id++ )
1655 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1658 if( ly_name.IsEmpty() )
1668 if( sublayer_id > 0 )
1669 ly_name += wxString::Format(
"_%d", sublayer_id );
1673 ly_name =
genString( ly_name,
"LAYER" );
1680 addAttribute( cadLayerNode,
"layerFunction",
"DIELCORE" );
1682 addAttribute( cadLayerNode,
"layerFunction",
"DIELPREG" );
1706 added_layers.insert( layer );
1707 wxXmlNode* cadLayerNode =
appendNode( aCadLayerNode,
"Layer" );
1728 for(
PAD*
pad : fp->Pads() )
1730 if(
pad->HasDrilledHole() )
1732 else if(
pad->HasHole() )
1739 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1740 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"DRILL" ) );
1745 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1752 wxXmlNode* drillNode =
appendNode( aCadLayerNode,
"Layer" );
1753 drillNode->AddAttribute(
"name",
genLayersString( layers.first, layers.second,
"SLOT" ) );
1759 wxXmlNode* spanNode =
appendNode( drillNode,
"Span" );
1768 wxXmlNode* stepNode =
appendNode( aCadNode,
"Step" );
1775 wxXmlNode* datumNode =
appendNode( stepNode,
"Datum" );
1795 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1802 wxXmlNode* xformNode =
appendNode( padNode,
"Xform" );
1803 xformNode->AddAttribute(
"rotation",
1811 addShape( padNode, *aPad, aLayer );
1815 wxXmlNode* pinRefNode =
appendNode( padNode,
"PinRef" );
1828 wxXmlNode* padNode =
appendNode( aContentNode,
"Pad" );
1849 addAttribute( aPadNode,
"padstackDefRef", th_pair->second );
1856 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1870 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1871 padStackHoleNode->AddAttribute(
"name",
1872 wxString::Format(
"%s%d_%d",
1873 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PTH" :
"NPTH",
1878 aPad->
GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
1893 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1895 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1900 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1903 addShape( padStackPadDefNode, shape );
1907 addShape( padStackPadDefNode, *aPad, layer );
1919 addAttribute( aContentNode,
"padstackDefRef", via_pair->second );
1926 wxXmlNode* padStackDefNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"PadStackDef" );
1931 wxXmlNode* padStackHoleNode =
appendNode( padStackDefNode,
"PadstackHoleDef" );
1934 addAttribute( padStackHoleNode,
"platingStatus",
"VIA" );
1947 PCB_SHAPE shape(
nullptr, SHAPE_T::CIRCLE );
1951 wxXmlNode* padStackPadDefNode =
appendNode( padStackDefNode,
"PadstackPadDef" );
1953 addAttribute( padStackPadDefNode,
"padUse",
"REGULAR" );
1956 addShape( padStackPadDefNode, shape );
1965 wxXmlNode* polygonNode =
nullptr;
1973 polygonNode =
appendNode( aParentNode,
"Polygon" );
1974 wxXmlNode* polybeginNode =
appendNode( polygonNode,
"PolyBegin" );
1976 const std::vector<VECTOR2I>& pts = aPolygon.
CPoints();
1977 addXY( polybeginNode, pts[0] );
1979 for(
size_t ii = 1; ii < pts.size(); ++ii )
1981 wxXmlNode* polyNode =
appendNode( polygonNode,
"PolyStepSegment" );
1982 addXY( polyNode, pts[ii] );
1985 wxXmlNode* polyendNode =
appendNode( polygonNode,
"PolyStepSegment" );
1986 addXY( polyendNode, pts[0] );
1990 if( aFillType == FILL_T::NO_FILL )
1997 addLineDesc( polygonNode, aWidth, aDashType,
true );
2001 wxCHECK( aWidth == 0,
false );
2014 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
2016 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
2018 wxXmlNode* cutoutNode =
appendNode( aParentNode,
"Cutout" );
2019 wxXmlNode* polybeginNode =
appendNode( cutoutNode,
"PolyBegin" );
2021 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
2022 addXY( polybeginNode, hole[0] );
2024 for(
size_t jj = 1; jj < hole.size(); ++jj )
2026 wxXmlNode* polyNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2027 addXY( polyNode, hole[jj] );
2030 wxXmlNode* polyendNode =
appendNode( cutoutNode,
"PolyStepSegment" );
2031 addXY( polyendNode, hole[0] );
2044 wxXmlNode* outlineNode =
appendNode( aParentNode,
"Outline" );
2064 outline = &bbox_outline;
2069 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to outline" ) );
2071 if( !outlineNode->GetChildren() )
2073 aParentNode->RemoveChild( outlineNode );
2085 int aOutline,
FILL_T aFillType,
int aWidth,
2091 wxXmlNode* contourNode =
appendNode( aParentNode,
"Contour" );
2096 if( aFillType != FILL_T::NO_FILL )
2101 aParentNode->RemoveChild( contourNode );
2116 wxLogError(
"Failed to get board outline" );
2120 wxXmlNode* profileNode =
appendNode( aStepNode,
"Profile" );
2124 wxLogTrace(
traceIpc2581, wxS(
"Failed to add polygon to profile" ) );
2125 aStepNode->RemoveChild( profileNode );
2133 std::unique_ptr<FOOTPRINT> fp(
static_cast<FOOTPRINT*
>( aFp->
Clone() ) );
2134 fp->SetParentGroup(
nullptr );
2135 fp->SetPosition( { 0, 0 } );
2137 if( fp->GetLayer() !=
F_Cu )
2138 fp->Flip( fp->GetPosition(), FLIP_DIRECTION::TOP_BOTTOM );
2140 fp->SetOrientation(
ANGLE_0 );
2144 fp->GetFPID().GetLibItemName().wx_str(),
2148 addAttribute( aContentNode,
"packageRef", iter->second );
2155 wxXmlNode* packageNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Package" );
2156 wxXmlNode* otherSideViewNode =
nullptr;
2162 if( fp->FindPadByNumber(
"1" ) )
2164 else if ( fp->FindPadByNumber(
"A1" ) )
2166 else if ( fp->FindPadByNumber(
"A" ) )
2168 else if ( fp->FindPadByNumber(
"a" ) )
2170 else if ( fp->FindPadByNumber(
"a1" ) )
2172 else if ( fp->FindPadByNumber(
"Anode" ) )
2174 else if ( fp->FindPadByNumber(
"ANODE" ) )
2179 addAttribute( packageNode,
"pinOneOrientation",
"OTHER" );
2189 otherSideViewNode =
appendNode( packageNode,
"OtherSideView" );
2191 LINE_STYLE::SOLID );
2200 wxXmlNode* pickupPointNode =
appendNode( packageNode,
"PickupPoint" );
2204 std::map<PCB_LAYER_ID, std::map<bool, std::vector<BOARD_ITEM*>>> elements;
2206 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2224 if( shape->
GetShape() == SHAPE_T::CIRCLE || shape->
GetShape() == SHAPE_T::RECTANGLE )
2228 elements[item->GetLayer()][is_abs].push_back( item );
2231 auto add_base_node =
2234 wxXmlNode* parent = packageNode;
2239 if( !otherSideViewNode )
2240 otherSideViewNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"OtherSideView" );
2242 parent = otherSideViewNode;
2248 name =
"SilkScreen";
2249 else if( aLayer ==
F_Fab || aLayer ==
B_Fab )
2250 name =
"AssemblyDrawing";
2258 auto add_marking_node =
2259 [&]( wxXmlNode* aNode ) -> wxXmlNode*
2261 wxXmlNode* marking_node =
appendNode( aNode,
"Marking" );
2263 return marking_node;
2266 std::map<PCB_LAYER_ID, wxXmlNode*> layer_nodes;
2267 std::map<PCB_LAYER_ID, BOX2I> layer_bbox;
2271 if( elements.find( layer ) != elements.end() )
2273 if( elements[layer][
true].size() > 0 )
2274 layer_bbox[layer] = elements[layer][
true][0]->GetBoundingBox();
2275 else if( elements[layer][
false].size() > 0 )
2276 layer_bbox[layer] = elements[layer][
false][0]->GetBoundingBox();
2280 for(
auto& [layer, map] : elements )
2282 wxXmlNode* layer_node = add_base_node( layer );
2283 wxXmlNode* marking_node = add_marking_node( layer_node );
2284 wxXmlNode* group_node =
appendNode( marking_node,
"UserSpecial" );
2285 bool update_bbox =
false;
2289 layer_nodes[layer] = layer_node;
2293 for(
auto& [is_abs, vec] : map )
2297 wxXmlNode* output_node =
nullptr;
2300 layer_bbox[layer].Merge( item->GetBoundingBox() );
2303 output_node = add_marking_node( layer_node );
2305 output_node = group_node;
2307 switch( item->Type() )
2313 if(
text->IsKnockout() )
2327 if(
text->IsBorderEnabled() )
2330 text->GetEffectiveShape()->TransformToPolygon( poly_set, 0,
ERROR_INSIDE );
2332 text->GetBorderWidth() );
2353 if( group_node->GetChildren() ==
nullptr )
2355 marking_node->RemoveChild( group_node );
2356 layer_node->RemoveChild( marking_node );
2358 delete marking_node;
2362 for(
auto&[layer, bbox] : layer_bbox )
2364 if( bbox.GetWidth() > 0 )
2366 wxXmlNode* outlineNode =
insertNode( layer_nodes[layer],
"Outline" );
2369 std::vector<VECTOR2I> points( 4 );
2370 points[0] = bbox.GetPosition();
2371 points[2] = bbox.GetEnd();
2372 points[1].x = points[0].x;
2373 points[1].y = points[2].y;
2374 points[3].x = points[2].x;
2375 points[3].y = points[0].y;
2377 outline.
Append( points );
2383 for(
size_t ii = 0; ii < fp->Pads().size(); ++ii )
2385 PAD*
pad = fp->Pads()[ii];
2386 wxXmlNode* pinNode =
appendNode( packageNode,
"Pin" );
2394 if(
pad->GetAttribute() == PAD_ATTRIB::NPTH )
2395 addAttribute( pinNode,
"electricalType",
"MECHANICAL" );
2396 else if(
pad->IsOnCopperLayer() )
2397 addAttribute( pinNode,
"electricalType",
"ELECTRICAL" );
2399 addAttribute( pinNode,
"electricalType",
"UNDEFINED" );
2401 if(
pad->HasHole() )
2406 if(
pad->GetFPRelativeOrientation() !=
ANGLE_0 )
2408 wxXmlNode* xformNode =
appendNode( pinNode,
"Xform" );
2409 xformNode->AddAttribute(
2411 floatVal(
pad->GetFPRelativeOrientation().Normalize().AsDegrees() ) );
2429 std::vector<wxXmlNode*> componentNodes;
2430 std::vector<wxXmlNode*> packageNodes;
2431 std::set<wxString> packageNames;
2433 bool generate_unique =
m_OEMRef.empty();
2437 wxXmlNode* componentNode =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Component" );
2439 wxXmlNode* pkg =
addPackage( componentNode, fp );
2442 packageNodes.push_back( pkg );
2448 if( !generate_unique )
2449 field = fp->GetFieldByName(
m_OEMRef );
2451 if( field && !field->
GetText().empty() )
2457 name = wxString::Format(
"%s_%s_%s", fp->GetFPID().GetFullLibraryName(),
2458 fp->GetFPID().GetLibItemName().wx_str(),
2463 wxLogError(
"Duplicate footprint pointers. Please report this bug." );
2470 else if( fp->GetAttributes() &
FP_SMD )
2475 if( fp->GetOrientation() !=
ANGLE_0 || fp->GetLayer() !=
F_Cu )
2477 wxXmlNode* xformNode =
appendNode( componentNode,
"Xform" );
2481 if( fp->GetLayer() ==
B_Cu )
2487 if( fp->GetLayer() !=
F_Cu )
2491 addLocationNode( componentNode, fp->GetPosition().x, fp->GetPosition().y );
2493 componentNodes.push_back( componentNode );
2502 for( wxXmlNode* pkg : packageNodes )
2503 aStepNode->AddChild( pkg );
2505 for( wxXmlNode* cmp : componentNodes )
2506 aStepNode->AddChild( cmp );
2514 wxXmlNode* netNode =
appendNode( aStepNode,
"LogicalNet" );
2518 for(
auto& [cmp,
pin] : pin_pair )
2520 wxXmlNode* netPinNode =
appendNode( netNode,
"PinRef" );
2534 std::vector<std::unique_ptr<FOOTPRINT>> footprints;
2538 std::map<PCB_LAYER_ID, std::map<int, std::vector<BOARD_ITEM*>>> elements;
2541 [&layers, &elements](
PCB_TRACK* aTrack )
2543 if( aTrack->Type() == PCB_VIA_T )
2545 PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
2547 for( PCB_LAYER_ID layer : layers )
2549 if( via->FlashLayer( layer ) )
2550 elements[layer][via->GetNetCode()].push_back( via );
2555 elements[aTrack->GetLayer()][aTrack->GetNetCode()].push_back( aTrack );
2559 std::for_each( m_board->Zones().begin(), m_board->Zones().end(),
2560 [ &elements ](
ZONE* zone )
2562 LSEQ zone_layers = zone->GetLayerSet().Seq();
2564 for( PCB_LAYER_ID layer : zone_layers )
2565 elements[layer][zone->GetNetCode()].push_back( zone );
2568 for(
BOARD_ITEM* item : m_board->Drawings() )
2571 elements[conn_it->GetLayer()][conn_it->GetNetCode()].push_back( conn_it );
2573 elements[item->GetLayer()][0].push_back( item );
2576 for(
FOOTPRINT* fp : m_board->Footprints() )
2578 for(
PCB_FIELD* field : fp->GetFields() )
2579 elements[field->GetLayer()][0].push_back( field );
2581 for(
BOARD_ITEM* item : fp->GraphicalItems() )
2582 elements[item->GetLayer()][0].push_back( item );
2584 for(
PAD*
pad : fp->Pads() )
2586 LSEQ pad_layers =
pad->GetLayerSet().Seq();
2590 if(
pad->FlashLayer( layer ) )
2591 elements[layer][
pad->GetNetCode()].push_back(
pad );
2598 if( m_progressReporter )
2599 m_progressReporter->SetMaxProgress( nets.GetNetCount() * layers.size() );
2601 wxXmlNode* layerNode = appendNode( aStepNode,
"LayerFeature" );
2602 addAttribute( layerNode,
"layerRef", m_layer_name_map[layer] );
2604 auto process_net = [&] (
int net )
2606 std::vector<BOARD_ITEM*>& vec = elements[layer][net];
2611 std::stable_sort( vec.begin(), vec.end(),
2614 if( a->GetParentFootprint() == b->GetParentFootprint() )
2615 return a->Type() < b->Type();
2617 return a->GetParentFootprint() < b->GetParentFootprint();
2620 generateLayerSetNet( layerNode, layer, vec );
2625 if( m_progressReporter )
2627 m_progressReporter->Report( wxString::Format(
_(
"Exporting Layer %s, Net %s" ),
2628 m_board->GetLayerName( layer ),
2629 net->GetNetname() ) );
2630 m_progressReporter->AdvanceProgress();
2633 process_net( net->GetNetCode() );
2636 if( layerNode->GetChildren() ==
nullptr )
2638 aStepNode->RemoveChild( layerNode );
2651 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2652 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"DRILL" ) );
2663 wxLogError(
"Failed to find padstack for via" );
2667 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2670 if(
via->GetNetCode() > 0 )
2673 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2674 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2679 addXY( holeNode,
via->GetPosition() );
2688 wxLogError(
"Failed to find padstack for pad" );
2692 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2695 if(
pad->GetNetCode() > 0 )
2698 wxXmlNode* holeNode =
appendNode( padNode,
"Hole" );
2699 addAttribute( holeNode,
"name", wxString::Format(
"H%d", hole_count++ ) );
2702 pad->GetAttribute() == PAD_ATTRIB::PTH ?
"PLATED" :
"NONPLATED" );
2705 addXY( holeNode,
pad->GetPosition() );
2714 wxXmlNode* layerNode =
appendNode( aLayerNode,
"LayerFeature" );
2715 layerNode->AddAttribute(
"layerRef",
genLayersString( layers.first, layers.second,
"SLOT" ) );
2719 wxXmlNode* padNode =
appendNode( layerNode,
"Set" );
2721 if(
pad->GetNetCode() > 0 )
2724 addSlotCavity( padNode, *
pad, wxString::Format(
"SLOT%d", hole_count++ ) );
2731 std::vector<BOARD_ITEM*>& aItems )
2733 auto it = aItems.begin();
2734 wxXmlNode* layerSetNode =
appendNode( aLayerNode,
"Set" );
2735 wxXmlNode* featureSetNode =
appendNode( layerSetNode,
"Features" );
2736 wxXmlNode* specialNode =
appendNode( featureSetNode,
"UserSpecial" );
2738 bool has_via =
false;
2739 bool has_pad =
false;
2741 wxXmlNode* padSetNode =
nullptr;
2743 wxXmlNode* viaSetNode =
nullptr;
2745 wxXmlNode* teardropLayerSetNode =
nullptr;
2746 wxXmlNode* teardropFeatureSetNode =
nullptr;
2751 if( item->GetNetCode() > 0 )
2760 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
2761 shape.
SetStart( track->GetStart() );
2762 shape.
SetEnd( track->GetEnd() );
2763 shape.
SetWidth( track->GetWidth() );
2769 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
2780 viaSetNode = layerSetNode;
2785 viaSetNode =
appendNode( layerSetNode,
"Set" );
2787 if( track->GetNetCode() > 0 )
2794 addVia( viaSetNode,
static_cast<PCB_VIA*
>( track ), aLayer );
2801 wxXmlNode* zoneFeatureNode = specialNode;
2803 if( zone->IsTeardropArea() &&
m_version >
'B' )
2805 if( !teardropFeatureSetNode )
2807 teardropLayerSetNode =
appendNode( aLayerNode,
"Set" );
2808 addAttribute( teardropLayerSetNode,
"geometryUsage",
"TEARDROP" );
2810 if( zone->GetNetCode() > 0 )
2813 genString( zone->GetNetname(),
"NET" ) );
2816 wxXmlNode* new_teardrops =
appendNode( teardropLayerSetNode,
"Features" );
2818 teardropFeatureSetNode =
appendNode( new_teardrops,
"UserSpecial" );
2821 zoneFeatureNode = teardropFeatureSetNode;
2827 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2828 wxString refDes =
componentName( zone->GetParentFootprint() );
2830 wxXmlNode* newFeatures =
appendNode( tempSetNode,
"Features" );
2832 zoneFeatureNode =
appendNode( newFeatures,
"UserSpecial" );
2836 SHAPE_POLY_SET& zone_shape = *zone->GetFilledPolysList( aLayer );
2838 for(
int ii = 0; ii < zone_shape.
OutlineCount(); ++ii )
2849 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2852 addAttribute( tempSetNode,
"geometryUsage",
"GRAPHIC" );
2856 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2861 else if( shape->GetShape() == SHAPE_T::CIRCLE
2862 || shape->GetShape() == SHAPE_T::RECTANGLE
2863 || shape->GetShape() == SHAPE_T::POLY )
2865 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2867 if( shape->GetNetCode() > 0 )
2870 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2887 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2889 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
2894 wxXmlNode* tempSetNode =
appendNode( aLayerNode,
"Set" );
2902 wxXmlNode* nonStandardAttributeNode =
appendNode( tempSetNode,
"NonstandardAttribute" );
2903 addAttribute( nonStandardAttributeNode,
"name",
"TEXT" );
2905 addAttribute( nonStandardAttributeNode,
"type",
"STRING" );
2907 wxXmlNode* tempFeature =
appendNode( tempSetNode,
"Features" );
2913 addText( tempFeature, text_item,
text->GetFontMetrics() );
2931 padSetNode = layerSetNode;
2936 padSetNode =
appendNode( aLayerNode,
"Set" );
2938 if(
pad->GetNetCode() > 0 )
2953 switch( item->Type() )
2958 add_track(
static_cast<PCB_TRACK*
>( item ) );
2966 add_pad(
static_cast<PAD*
>( item ) );
2970 add_shape(
static_cast<PCB_SHAPE*
>( item ) );
2995 if( specialNode->GetChildren() ==
nullptr )
2997 featureSetNode->RemoveChild( specialNode );
3001 if( featureSetNode->GetChildren() ==
nullptr )
3003 layerSetNode->RemoveChild( featureSetNode );
3004 delete featureSetNode;
3007 if( layerSetNode->GetChildren() ==
nullptr )
3009 aLayerNode->RemoveChild( layerSetNode );
3010 delete layerSetNode;
3023 wxXmlNode* header =
appendNode( avl,
"AvlHeader" );
3027 addAttribute( header,
"datetime", wxDateTime::Now().FormatISOCombined() );
3030 std::set<wxString> unique_parts;
3031 std::map<wxString,wxString> unique_vendors;
3035 auto [ it, success ] = unique_parts.insert(
name );
3040 wxXmlNode* part =
appendNode( avl,
"AvlItem" );
3044 PCB_FIELD* company[2] = { fp->GetFieldByName(
m_mfg ),
nullptr };
3047 for (
int ii = 0; ii < 2; ++ii )
3053 if( mpn_name.empty() )
3056 wxXmlNode* vmpn =
appendNode( part,
"AvlVmpn" );
3060 wxXmlNode* mpn =
appendNode( vmpn,
"AvlMpn" );
3063 wxXmlNode* vendor =
appendNode( vmpn,
"AvlVendor" );
3065 wxString
name = wxT(
"UNKNOWN" );
3068 if( !ii && company[ii] )
3076 else if( !ii && !company_name[ii].
empty() )
3078 name = company_name[ii];
3080 else if( ii && !
m_dist.empty() )
3085 auto [vendor_id, inserted] = unique_vendors.emplace(
3087 wxString::Format(
"VENDOR_%zu", unique_vendors.size() ) );
3089 addAttribute( vendor,
"enterpriseRef", vendor_id->second );
3093 wxXmlNode* new_vendor =
new wxXmlNode( wxXML_ELEMENT_NODE,
"Enterprise" );
3109 const std::map<std::string, UTF8>* aProperties )
3116 if(
auto it = aProperties->find(
"units" ); it != aProperties->end() )
3118 if( it->second ==
"inch" )
3125 if(
auto it = aProperties->find(
"sigfig" ); it != aProperties->end() )
3126 m_sigfig = std::stoi( it->second );
3128 if(
auto it = aProperties->find(
"version" ); it != aProperties->end() )
3131 if(
auto it = aProperties->find(
"OEMRef" ); it != aProperties->end() )
3134 if(
auto it = aProperties->find(
"mpn" ); it != aProperties->end() )
3135 m_mpn = it->second.wx_str();
3137 if(
auto it = aProperties->find(
"mfg" ); it != aProperties->end() )
3138 m_mfg = it->second.wx_str();
3140 if(
auto it = aProperties->find(
"dist" ); it != aProperties->end() )
3141 m_dist = it->second.wx_str();
3143 if(
auto it = aProperties->find(
"distpn" ); it != aProperties->end() )
3148 for(
char c =
'a'; c <=
'z'; ++c )
3151 for(
char c =
'A'; c <=
'Z'; ++c )
3154 for(
char c =
'0'; c <=
'9'; ++c )
3158 std::string specialChars =
"_\\-.+><";
3160 for(
char c : specialChars )
3189 double written_bytes = 0.0;
3190 double last_yield = 0.0;
3197 auto update_progress = [&](
size_t aBytes )
3199 written_bytes += aBytes;
3200 double percent = written_bytes /
static_cast<double>(
m_total_bytes );
3205 if( last_yield + 0.01 < percent )
3207 last_yield = percent;
3217 wxLogError(
_(
"Failed to save file to buffer" ) );
3221 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