31#include <unordered_set>
71template <
typename BLK_T>
74 return static_cast<const BLOCK<BLK_T>&
>( aBlock ).GetData();
78#define BLK_FIELD( BLK_T, FIELD ) BlockDataAs<BLK_T>( aBlock ).FIELD
137 wxString::Format(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x",
211 LL_WALKER( aList.m_Head, aList.m_Tail, aBoard )
235 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
248static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
332 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
355 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
379 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
388 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
396 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
416 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
433 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
442 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
446 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
450 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
456 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
480 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
482 if( classIt != s_ClassNames.end() )
483 className = classIt->second;
485 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
487 wxString subclassName;
490 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
492 if( classMapIt != s_SubclassNameMaps.end() )
494 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
496 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
498 if( subIt != subclassMap.end() )
499 subclassName = subIt->second;
503 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
509 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
512 return className + wxS(
"/" ) + subclassName;
555 return trace.m_Layer;
565 return shape.m_Layer;
583 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
585 return layerInfo.value();
617 if(
m_Lists.count( &aList ) == 0 )
619 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
625 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
634 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
644 classLayers.size(), aClass, aList.
m_Key );
666 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
667 const size_t numCuLayers = etchLayers.size();
669 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
671 std::vector<INPUT_LAYER_DESC> inputLayers;
673 for(
size_t li = 0; li < numCuLayers; ++li )
676 desc.
Name = etchLayers[li].m_Name;
680 inputLayers.push_back( desc );
685 int nextAutoUser = 0;
692 for(
size_t si = 0; si < layerList->size(); ++si )
694 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
703 if( layerList->at( si ).m_Name.length() > 0 )
704 desc.
Name = layerList->at( si ).m_Name;
709 inputLayers.push_back( desc );
720 desc.
Name = layerName;
724 inputLayers.push_back( desc );
734 inputLayers.push_back( desc );
740 for(
size_t li = 0; li < numCuLayers; ++li )
743 const wxString& layerName = etchLayers[li].m_Name;
745 auto it = resolvedMapping.find( layerName );
746 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
750 m_board.SetLayerName( lId, layerName );
754 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
758 auto rmIt = resolvedMapping.find( displayName );
769 auto rmIt = resolvedMapping.find( dialogName );
774 m_board.SetLayerName( rmIt->second, dialogName );
779 LSET enabledLayersMask =
m_board.GetEnabledLayers();
781 for(
const auto& [
name, layerId] : resolvedMapping )
784 enabledLayersMask |=
LSET{ layerId };
790 m_board.GetLayerName( layerId ), layerId );
794 m_board.SetEnabledLayers( enabledLayersMask );
796 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
821 && cLayerList == etchIt->second
822 && aLayerInfo.
m_Subclass < cLayerList->size() )
830 if( aLayerInfo.
m_Subclass < cLayerList->size() )
882 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
970 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
984 if( aNum == aTotal - 1 )
1017 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
1018 m_board.SetLayerName( lId, aName );
1025 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
1088 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
1091 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
1094 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1177 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1187 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1202 double result = std::round( aValue );
1204 if(
result > std::numeric_limits<int>::max() )
1205 return std::numeric_limits<int>::max();
1207 if(
result < std::numeric_limits<int>::min() )
1208 return std::numeric_limits<int>::min();
1210 return static_cast<int>(
result );
1245 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1251 const wxString& aName )
const
1253 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1254 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1255 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#lx ", aOffset );
1257 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1268 if( blk0x30 ==
nullptr )
1273 if( blk0x31 ==
nullptr )
1284 bool encountered =
false;
1288 if( block->GetBlockType() != 0x36 )
1293 if( blk0x36.
m_Code != 0x08 )
1304 for(
const auto& item : blk0x36.
m_Items )
1306 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1322 std::vector<BOARD_ITEM*> bulkAdded;
1328 const uint8_t type = block->GetBlockType();
1338 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1343 if( netName.IsEmpty() )
1344 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1346 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1350 bulkAdded.push_back( kiNetInfo.get() );
1354 m_board.FinalizeBulkAdd( bulkAdded );
1364 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1365 return wxEmptyString;
1368 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1371 return wxEmptyString;
1375 size_t sep = str->find(
":\\" );
1377 if( sep == std::string::npos )
1378 return wxEmptyString;
1380 std::string extracted = str->substr( sep + 2 );
1382 if( !extracted.empty() && extracted.back() ==
'\\' )
1383 extracted.pop_back();
1385 return wxString( extracted );
1394 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1403 int diffPairGap = 0;
1407 std::map<wxString, CS_DEF> constraintSets;
1410 std::map<uint32_t, wxString> keyToSetName;
1417 if( block->GetBlockType() != 0x1D )
1425 if( resolved && !resolved->IsEmpty() )
1427 setName = *resolved;
1435 if( setName.IsEmpty() )
1436 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1442 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1447 const auto& record = csBlock.
m_DataB[0];
1449 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1450 memcpy( fields, record.data(),
sizeof( fields ) );
1457 def.lineWidth =
scale( fields[1] );
1458 def.clearance =
scale( fields[4] );
1464 def.lineWidth =
scale( fields[0] );
1465 def.clearance =
scale( fields[1] );
1468 def.diffPairGap =
scale( fields[7] );
1470 constraintSets[setName] = def;
1474 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1475 setName, def.lineWidth, def.clearance, def.diffPairGap );
1478 if( constraintSets.empty() )
1485 for(
const auto& [
name, def] : constraintSets )
1487 wxString ncName =
name;
1490 ncName = wxS(
"Allegro_Default" );
1492 if( netSettings->HasNetclass( ncName ) )
1495 auto nc = std::make_shared<NETCLASS>( ncName );
1497 if( def.lineWidth > 0 )
1498 nc->SetTrackWidth( def.lineWidth );
1500 if( def.clearance > 0 )
1501 nc->SetClearance( def.clearance );
1503 if( def.diffPairGap > 0 )
1505 nc->SetDiffPairGap( def.diffPairGap );
1508 if( def.lineWidth > 0 )
1509 nc->SetDiffPairWidth( def.lineWidth );
1512 netSettings->SetNetclass( ncName, nc );
1518 wxString defaultSetName;
1520 for(
const auto& [
name, def] : constraintSets )
1522 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1524 defaultSetName =
name;
1540 wxString assignedSetName;
1542 if( csField.has_value() )
1544 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1546 auto it = keyToSetName.find( *intVal );
1548 if( it != keyToSetName.end() )
1549 assignedSetName = it->second;
1551 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1553 if( constraintSets.count( *strVal ) )
1554 assignedSetName = *strVal;
1559 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1560 assignedSetName = defaultSetName;
1562 if( assignedSetName.IsEmpty() )
1565 wxString ncName = assignedSetName;
1568 ncName = wxS(
"Allegro_Default" );
1570 if( !netSettings->HasNetclass( ncName ) )
1579 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1580 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1583 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1592 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1596 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1605 if( !minWidth.has_value() || minWidth.value() <= 0 )
1608 int widthNm =
scale( minWidth.value() );
1609 widthToNetKeys[widthNm].push_back( aView.
m_Net->
GetKey() );
1612 if( widthToNetKeys.empty() )
1618 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1620 int widthMils = ( widthNm + 12700 ) / 25400;
1621 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1623 if( netSettings->HasNetclass( ncName ) )
1626 auto nc = std::make_shared<NETCLASS>( ncName );
1627 nc->SetTrackWidth( widthNm );
1628 netSettings->SetNetclass( ncName, nc );
1630 for( uint32_t netKey : netKeys )
1638 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1642 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1643 ncName, widthNm, netKeys.size() );
1646 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1647 widthToNetKeys.size() );
1654 return wxEmptyString;
1659 return wxEmptyString;
1661 uint32_t tableKey = 0;
1667 tableKey = x26.m_GroupPtr;
1674 if(
next &&
next->GetBlockType() == 0x26 )
1677 tableKey = x26b.m_GroupPtr;
1688 return wxEmptyString;
1692 return wxEmptyString;
1698 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1699 return wxEmptyString;
1704 return wxEmptyString;
1708 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1717 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1720 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1723 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1735 if( groupName.empty() )
1738 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1741 if( groupToNetKeys.empty() )
1750 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1754 bool isDiffPair = ( netKeys.size() == 2 );
1755 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1756 wxString ncName = ncPrefix + groupName;
1758 if( netSettings->HasNetclass( ncName ) )
1761 auto nc = std::make_shared<NETCLASS>( ncName );
1765 for( uint32_t netKey : netKeys )
1772 NETCLASS* existing = it->second->GetNetClass();
1792 netSettings->SetNetclass( ncName, nc );
1794 for( uint32_t netKey : netKeys )
1802 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1812 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1813 groupName, ncName, netKeys.size() );
1817 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1818 dpCount, mgCount, groupToNetKeys.size() );
1837 std::unordered_set<LAYER_INFO> layersFound;
1839 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1841 if(
info.has_value() )
1843 layersFound.insert( std::move(
info.value() ) );
1857 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1858 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1859 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1869 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1871 for(
size_t i = 0; i < layerMap.size(); ++i )
1873 const uint8_t classNum =
static_cast<uint8_t
>( i );
1875 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1904 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1908 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1921 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1947 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1948 shape->SetLayer( aLayer );
1949 shape->SetStart( start );
1950 shape->SetEnd(
end );
1953 int adjustedWidth = width;
1955 if( adjustedWidth <= 0 )
1956 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1958 shape->SetWidth( adjustedWidth );
1971 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1973 shape->SetLayer( aLayer );
1978 start.Format(),
end.Format() );
1981 start =
scale( start );
1988 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1994 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1996 shape->SetWidth( arcWidth );
2002 shape->SetCenter( c );
2003 shape->SetRadius(
radius );
2014 EDA_ANGLE angle = endangle - startangle;
2016 if( clockwise && angle <
ANGLE_0 )
2018 if( !clockwise && angle >
ANGLE_0 )
2027 shape->SetArcGeometry( start, mid,
end );
2037 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
2040 text->SetLayer( layer );
2046 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
2047 "in string wrapper (0x30) with key %#010x",
2055 if( aStrWrapper.
m_Font.has_value() )
2056 props = &aStrWrapper.
m_Font.value();
2058 if( !props && aStrWrapper.
m_Font16x.has_value() )
2064 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
2065 aStrWrapper.
m_Key ),
2081 text->SetTextAngle( textAngle );
2090 text->SetPosition( textPos + textFontOffset );
2093 text->SetMirrored(
true );
2118 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2120 const uint32_t markerShape = aPinDef.
GetShape();
2126 const auto addLine = [&](
const SEG& aSeg )
2128 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
2129 shape->SetStart( aSeg.A );
2130 shape->SetEnd( aSeg.B );
2131 shapes.push_back( std::move( shape ) );
2134 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
2136 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
2137 shape->SetPolyPoints( aPts );
2138 shapes.push_back( std::move( shape ) );
2141 switch( markerShape )
2145 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
2146 shape->SetCenter(
center );
2147 shape->SetRadius( size.x / 2 );
2148 shapes.push_back( std::move( shape ) );
2154 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2155 shape->SetStart(
center - size / 2 );
2156 shape->SetEnd(
center + size / 2 );
2157 shapes.push_back( std::move( shape ) );
2162 std::unique_ptr<PCB_SHAPE> shape;
2166 for(
const SEG& seg : segs )
2175 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2176 shape->SetStart(
center - size / 2 );
2177 shape->SetEnd(
center + size / 2 );
2179 int minSize = std::min( size.x, size.y );
2180 shape->SetCornerRadius(
minSize / 2 );
2181 shapes.push_back( std::move( shape ) );
2223 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2224 markerShape, aPinDef.
m_Key );
2229 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2230 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2232 shape->SetLayer( layer );
2233 shape->SetWidth( 0 );
2235 items.push_back( std::move( shape ) );
2245 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2258 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2260 newItems.push_back( std::move( shape ) );
2266 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2267 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2268 newItems.push_back( std::move( shape ) );
2274 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2276 newItems.push_back( std::move( shape ) );
2282 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2284 newItems.push_back( std::move( shape ) );
2291 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2293 newItems.push_back( std::move( newItem ) );
2316 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2330 for(
const BLOCK_BASE* segBlock : segWalker )
2332 std::unique_ptr<PCB_SHAPE> shape;
2334 switch( segBlock->GetBlockType() )
2353 segBlock->GetBlockType() );
2359 shapes.push_back( std::move( shape ) );
2368 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2371 shape->SetLayer( layer );
2378 shape->SetStart( cornerA );
2379 shape->SetEnd( cornerB );
2382 shape->Rotate( cornerA, angle );
2384 const int lineWidth = 0;
2385 shape->SetWidth( lineWidth );
2393 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2396 shape->SetLayer( layer );
2403 shape->SetStart( cornerA );
2404 shape->SetEnd( cornerB );
2407 shape->Rotate( cornerA, angle );
2409 const int lineWidth = 0;
2410 shape->SetWidth( lineWidth );
2418 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2421 shape->SetLayer( layer );
2427 if(
chain.PointCount() < 3 )
2429 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2434 chain.SetClosed(
true );
2435 shape->SetPolyShape(
chain );
2437 const int lineWidth = 0;
2438 shape->SetWidth( lineWidth );
2447 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2454 for(
const BLOCK_BASE* segBlock : segWalker )
2456 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2457 shape->SetLayer( layer );
2458 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2460 switch( segBlock->GetBlockType() )
2474 shape->SetCenter( c );
2475 shape->SetRadius(
radius );
2481 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2489 EDA_ANGLE angle = endangle - startangle;
2491 if( clockwise && angle <
ANGLE_0 )
2494 if( !clockwise && angle >
ANGLE_0 )
2500 shape->SetArcGeometry( start, mid,
end );
2513 shape->SetStart( start );
2514 shape->SetEnd(
end );
2515 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2519 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2523 shapes.push_back( std::move( shape ) );
2532 uint32_t refKey = 0x00;
2550 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2556 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2558 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
GetLayerCount() );
2561 std::optional<int> thermalGap;
2563 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2582 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2589 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2595 auto& layerCuProps = copperLayers[i];
2597 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2631 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.
value() / (double) minDim;
2633 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2646 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.
value() / (double) minDim;
2648 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2660 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2674 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2675 padStackName, i, padComp.
m_StrPtr );
2690 int anchorSize =
static_cast<int>(
2693 if( anchorSize < 1 )
2696 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2698 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2700 poly->SetFilled(
true );
2701 poly->SetWidth( 0 );
2702 layerCuProps->custom_shapes.push_back( poly );
2707 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2719 const int w = std::max( padComp.
m_W, 300 );
2720 const int h = std::max( padComp.
m_H, 220 );
2723 auto S = [&](
int x,
int y )
2729 outline.
Append(
S( 0, -h / 2 ) );
2730 outline.
Append(
S( w / 2, -h / 6 ) );
2731 outline.
Append(
S( w / 3, h / 2 ) );
2732 outline.
Append(
S( -w / 3, h / 2 ) );
2733 outline.
Append(
S( -w / 2, -h / 6 ) );
2737 int anchorSize =
static_cast<int>(
2740 if( anchorSize < 1 )
2743 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2745 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2747 poly->SetFilled(
true );
2748 poly->SetWidth( 0 );
2749 layerCuProps->custom_shapes.push_back( poly );
2754 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2755 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2765 "differs from pad shape %d",
2769 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2770 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2772 if( clearanceX && clearanceX != clearanceY )
2775 "clearance X=%d Y=%d",
2776 padStackName, i, clearanceX, clearanceY );
2779 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2783 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2786 layerCuProps->clearance = clearanceX;
2795 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2802 "Padstack %s: thermal relief type=%d, gap=%snm",
2803 padStackName, thermalComp.
m_Type,
2804 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2805 : wxString(
"N/A" ) );
2815 if( copperLayers.size() == 0 )
2821 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2824 for(
size_t i = aFrom + 1; i < aTo; ++i )
2826 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2835 for(
size_t i = 0; i < copperLayers.size(); ++i )
2837 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2842 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2847 layerProps = *copperLayers.front();
2849 else if( copperLayers.front() && copperLayers.back()
2850 && layersEqual( 1, copperLayers.size() - 1 ) )
2852 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2858 if( copperLayers.size() > 2 && copperLayers[1] )
2866 for(
size_t i = 0; i < copperLayers.size(); ++i )
2868 if( !copperLayers[i] )
2875 else if( i == copperLayers.size() - 1 )
2899 if( std::holds_alternative<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header ) )
2901 const auto& hdr16x = std::get<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header );
2903 if( hdr16x.m_SlotY > 0 )
2905 drillW =
scale(
static_cast<int>( hdr16x.m_SlotX ) );
2906 drillH =
scale(
static_cast<int>( hdr16x.m_SlotY ) );
2915 const auto& hdr17x = std::get<BLK_0x1C_PADSTACK::HEADER_v17x>( aPadstack.
m_Header );
2917 if( hdr17x.m_SlotY > 0 )
2919 drillW =
scale(
static_cast<int>( hdr17x.m_SlotX ) );
2920 drillH =
scale(
static_cast<int>( hdr17x.m_SlotY ) );
2924 drillW =
scale(
static_cast<int>( hdr17x.m_DrillSize ) );
2941 bool drillIsTaller = ( drillH > drillW );
2943 if( padIsTaller != drillIsTaller )
2944 std::swap( drillW, drillH );
2947 bool isSmd = ( drillW == 0 ) || ( aPadstack.
GetLayerCount() == 1 );
2957 if( drillW != drillH )
2963 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2964 pad->SetPadstack( padStack );
2965 pad->SetNumber( aPadName );
2966 pad->SetNetCode( aNetcode );
2984 if( thermalGap.has_value() )
2985 pad->SetThermalGap( thermalGap.value() );
2987 padItems.push_back( std::move(
pad ) );
3003 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
3004 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
3013 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
3017 const bool backSide = ( aFpInstance.
m_Layer != 0 );
3026 if( refDesStr.IsEmpty() )
3029 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
3036 fp->SetReference( refDesStr );
3049 fp->SetPosition( fpPos );
3050 fp->SetOrientation( rotation );
3065 const auto canonicalizeLayer = [backSide, fpPos](
BOARD_ITEM* aItem )
3073 for(
const BLOCK_BASE* graphicsBlock : graphicsWalker )
3075 const uint8_t type = graphicsBlock->GetBlockType();
3081 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
3083 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
3085 canonicalizeLayer( shape.get() );
3086 fp->Add( shape.release() );
3091 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", type ),
3096 bool valueFieldSet =
false;
3100 for(
const BLOCK_BASE* textBlock : textWalker )
3102 const uint8_t type = textBlock->GetBlockType();
3114 canonicalizeLayer(
text.get() );
3116 const uint8_t textClass = strWrapper.m_Layer.m_Class;
3117 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
3130 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
3131 text->SetText( wxString(
"UNK" ) +
text->GetText() );
3139 field->
SetText( wxS(
"${REFERENCE}" ) );
3145 if( !valueFieldSet )
3151 valueFieldSet =
true;
3186 fp->Add(
text.release() );
3193 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3195 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3197 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3199 canonicalizeLayer( item.get() );
3200 fp->Add( item.release() );
3210 for(
const BLOCK_BASE* areaBlock : areaWalker )
3214 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3217 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler );
3220 canonicalizeLayer( zone.get() );
3221 fp->Add( zone.release() );
3226 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3228 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3230 canonicalizeLayer( item.get() );
3245 fp->Add( item.release() );
3253 for(
const BLOCK_BASE* padBlock : padWalker )
3275 netCode = netIt->second->GetNetCode();
3295 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3297 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3301 PAD*
pad =
static_cast<PAD*
>( item.get() );
3302 pad->SetFPRelativeOrientation( padLocalRot );
3305 item->SetFPRelativePosition( padLocalPos );
3306 fp->Add( item.release() );
3324 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3330 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3340 const uint8_t segType = block->GetBlockType();
3353 int width =
static_cast<int>( segInfo.
m_Width );
3355 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3357 seg->SetNetCode( aNetCode );
3358 seg->SetLayer( layer );
3360 seg->SetStart(
scale( start ) );
3362 seg->SetWidth(
scale( width ) );
3364 items.push_back( std::move( seg ) );
3374 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3376 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3383 EDA_ANGLE angle = endAngle - startAngle;
3385 if( clockwise && angle <
ANGLE_0 )
3388 if( !clockwise && angle >
ANGLE_0 )
3394 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3396 arc->SetNetCode( aNetCode );
3397 arc->SetLayer( layer );
3399 arc->SetStart( start );
3402 arc->SetWidth( width );
3404 items.push_back( std::move( arc ) );
3425 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3426 via->SetPosition(
scale( viaPos ) );
3427 via->SetNetCode( aNetCode );
3451 viaDrill = viaWidth / 2;
3452 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3453 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack '%s' key %#010x, using fallback %d",
3459 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3461 "Via at (%d, %d) in padstack '%s' key %#010x has no valid pad component, using drill-based "
3462 "fallback (%d * 2)",
3464 viaWidth = viaDrill * 2;
3467 via->SetWidth(
F_Cu, viaWidth );
3468 via->SetDrill( viaDrill );
3478 std::vector<BOARD_ITEM*> newItems;
3484 const uint8_t type = block->GetBlockType();
3498 const int netCode = netIt->second->GetNetCode();
3501 for(
const BLOCK_BASE* assignBlock : assignmentWalker )
3503 if( assignBlock->GetBlockType() != 0x04 )
3513 for(
const BLOCK_BASE* connItemBlock : connWalker )
3515 const uint8_t connType = connItemBlock->GetBlockType();
3519 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3528 newItemList =
buildTrack( trackData, netCode );
3534 newItemList.push_back(
buildVia( viaData, netCode ) );
3565 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3567 newItems.push_back( newItem.get() );
3574 m_board.FinalizeBulkAdd( newItems );
3576 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3588 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3594 switch( block->GetBlockType() )
3605 newItems.push_back( std::move( rectShape ) );
3618 for(
auto& shapeItem : shapeItems )
3619 newItems.push_back( std::move( shapeItem ) );
3624 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3634 for(
const BLOCK_BASE* block : outline2Walker )
3638 switch( block->GetBlockType() )
3648 newItems.push_back( std::move( rectShape ) );
3659 newItems.push_back( std::move( rectShape ) );
3671 for(
auto& shapeItem : shapeItems )
3672 newItems.push_back( std::move( shapeItem ) );
3677 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3687 for(
const BLOCK_BASE* block : graphicContainerWalker )
3691 switch( block->GetBlockType() )
3700 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3702 for(
auto& item : graphicItems )
3703 newItems.push_back( std::move( item ) );
3708 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in graphic container walker: %#04x",
3709 block->GetBlockType() );
3717 std::vector<BOARD_ITEM*> addedItems;
3718 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3720 addedItems.push_back( item.get() );
3724 m_board.FinalizeBulkAdd( addedItems );
3735 return cacheIt->second;
3738 uint32_t currentKey = aStartKey;
3741 static constexpr int MAX_CHAIN_LENGTH = 50000;
3744 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3765 outline.
Append( shapeArc );
3769 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3776 EDA_ANGLE arcAngle = endAngle - startAngle;
3778 if( clockwise && arcAngle <
ANGLE_0 )
3781 if( !clockwise && arcAngle >
ANGLE_0 )
3788 outline.
Append( shapeArc );
3791 currentKey = arc.m_Next;
3807 currentKey = seg.m_Next;
3826 VECTOR2I topRight{ botRight.x, topLeft.
y };
3827 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3829 outline.
Append( topLeft );
3830 outline.
Append( topRight );
3831 outline.
Append( botRight );
3832 outline.
Append( botLeft );
3835 outline.
Rotate( angle, topLeft );
3847 VECTOR2I topRight{ botRight.x, topLeft.
y };
3848 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3850 outline.
Append( topLeft );
3851 outline.
Append( topRight );
3852 outline.
Append( botRight );
3853 outline.
Append( botLeft );
3856 outline.
Rotate( angle, topLeft );
3867 for(
const BLOCK_BASE* segBlock : segWalker )
3869 switch( segBlock->GetBlockType() )
3881 outline.
Append( shapeArc );
3885 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3892 EDA_ANGLE arcAngle = endAngle - startAngle;
3894 if( clockwise && arcAngle <
ANGLE_0 )
3897 if( !clockwise && arcAngle >
ANGLE_0 )
3904 outline.
Append( shapeArc );
3925 segBlock->GetBlockType() );
3951 while( holeKey != 0 )
3965 polySet.
AddHole( holeOutline );
3968 holeKey = keepout.m_Next;
3986 chain.SetClosed(
true );
3996 chain.SetClosed(
true );
4006 chain.SetClosed(
true );
4026 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
4059 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
4068 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
4073 auto zone = std::make_unique<ZONE>( &
m_board );
4078 zone->SetLayer( layer );
4091 zone->SetIsRuleArea(
true );
4092 zone->SetLayerSet( layerSet );
4093 zone->SetDoNotAllowTracks( isRouteKeepout );
4094 zone->SetDoNotAllowVias( isViaKeepout );
4095 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
4096 zone->SetDoNotAllowPads(
false );
4097 zone->SetDoNotAllowFootprints( isPackageKeepout );
4103 zone->SetZoneName(
"Route Keepin" );
4104 else if( isPackageKeepin )
4105 zone->SetZoneName(
"Package Keepin" );
4110 for(
const BLOCK_BASE* block : aRelatedBlocks )
4115 switch( block->GetBlockType() )
4119 const auto it =
m_netCache.find( block->GetKey() );
4124 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
4126 netCode = it->second->GetNetCode();
4130 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
4131 block->GetKey(), aBoundaryBlock.
GetKey() ),
4141 combinedFill.
Append( fillPolySet );
4151 zone->SetNetCode( netCode );
4157 if( isCopperZone && !combinedFill.
IsEmpty() )
4171 zone->SetIsFilled(
true );
4172 zone->SetNeedRefill(
false );
4185 std::vector<const BLOCK_BASE*> ret;
4198 if( !ptrArray || ptrArray->
m_Count == 0 )
4201 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4202 ret.resize( count );
4204 for(
size_t i = 0; i < count; i++ )
4218 if( block->GetBlockType() != 0x30 )
4221 const auto& strWrapper =
4231 if( strWrapper.GetGroupPtr() != 0 )
4239 text->GetPosition().x,
text->GetPosition().y );
4249template <std::derived_from<BOARD_ITEM> T>
4252 std::vector<BOARD_ITEM*> rawPointers;
4253 rawPointers.reserve( aItems.size() );
4255 for( std::unique_ptr<T>& item : aItems )
4257 rawPointers.push_back( item.get() );
4269 std::vector<std::unique_ptr<ZONE>> newZones;
4270 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4280 std::unique_ptr<ZONE> zone;
4283 switch( block->GetBlockType() )
4292 zone =
buildZone( *block, {}, zoneFillHandler );
4303 zone =
buildZone( *block, {}, zoneFillHandler );
4315 layerInfo = shapeData.
m_Layer;
4320 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4321 block->GetBlockType(), block->GetKey() );
4328 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4329 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4330 layerInfo.m_Subclass );
4332 newZones.push_back( std::move( zone ) );
4339 for(
const BLOCK_BASE* block : keepoutWalker )
4341 std::unique_ptr<ZONE> zone;
4343 switch( block->GetBlockType() )
4355 zone =
buildZone( *block, {}, zoneFillHandler );
4368 zone =
buildZone( *block, {}, zoneFillHandler );
4377 newZones.push_back( std::move( zone ) );
4384 int originalCount = newZones.size();
4393 int mergedCount = mergedZones.size();
4395 int keepoutCount = 0;
4396 int boundaryCount = 0;
4398 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4400 if( zone->GetIsRuleArea() )
4408 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4409 keepoutCount, originalCount - mergedCount );
4420 if( block->GetBlockType() != 0x2C )
4433 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4437 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4439 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4448 switch( keyTable->GetBlockType() )
4455 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4457 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4459 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4461 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4476 newItems.push_back( std::move( newItem ) );
4493 keyTable->GetBlockType() );
4499 if( newItems.size() > 0 )
4501 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4503 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4504 group->SetName( tableName );
4506 for(
const auto& item : newItems )
4507 group->AddItem( item.get() );
4509 newItems.push_back( std::move(
group ) );
4532 int copperShapeCount = 0;
4533 int teardropCount = 0;
4548 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4550 if( isDynCopperShape )
4552 auto zone = std::make_unique<ZONE>( &
m_board );
4555 zone->SetLayer( fill.layer );
4556 zone->SetNetCode( fill.netCode );
4557 zone->SetLocalClearance( 0 );
4563 zone->AddPolygon(
chain );
4565 zone->SetFilledPolysList( fill.layer, fractured );
4566 zone->SetIsFilled(
true );
4567 zone->SetNeedRefill(
false );
4568 zone->CalculateFilledArea();
4576 shape->SetPolyShape( fractured );
4577 shape->SetFilled(
true );
4578 shape->SetLayer( fill.layer );
4579 shape->SetNetCode( fill.netCode );
4588 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4589 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4595 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4599 if( zone->IsTeardropArea() )
4600 teardropsByNet[zone->GetNetCode()].push_back( zone );
4603 if( teardropsByNet.empty() )
4611 for(
PAD*
pad : fp->Pads() )
4613 auto it = teardropsByNet.find(
pad->GetNetCode() );
4615 if( it == teardropsByNet.end() )
4618 for(
ZONE* tdZone : it->second )
4625 pad->SetTeardropsEnabled(
true );
4639 auto it = teardropsByNet.find(
via->GetNetCode() );
4641 if( it == teardropsByNet.end() )
4644 for(
ZONE* tdZone : it->second )
4651 via->SetTeardropsEnabled(
true );
4658 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4666 static_cast<int>(
m_brdDb.m_FmtVer ),
4669 m_brdDb.m_Header->m_AllegroVersion.data() );
4742 std::vector<BOARD_ITEM*> bulkAddedItems;
4744 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4746 for(
const BLOCK_BASE* fpContainer : fpWalker )
4748 if( fpContainer->GetBlockType() == 0x2B )
4755 for(
const BLOCK_BASE* instBlock : instWalker )
4757 if( instBlock->GetBlockType() != 0x2D )
4760 wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4761 instBlock->GetBlockType(), fpBlock.
m_Key ),
4773 bulkAddedItems.push_back( fp.get() );
4779 wxString::Format(
"Failed to construct footprint for 0x2D key %#010x",
4791 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4792 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4794 if( !bulkAddedItems.empty() )
4795 m_board.FinalizeBulkAdd( bulkAddedItems );
static std::unordered_set< LAYER_INFO > ScanForLayers(const BRD_DB &aDb)
Look through some lists for a list of layers used.
static uint32_t GetPrimaryNext(const BLOCK_BASE &aBlock)
Gets the next block in the linked list.
static std::optional< LAYER_INFO > tryLayerFromBlock(const BLOCK_BASE &aBlock)
Some blocks report layer info - if they do, return it else std::nullopt.
static wxString layerInfoDisplayName(const LAYER_INFO &aLayerInfo)
Build a unique display name for a LAYER_INFO entry from the static maps above, suitable for presentat...
static bool layerIsZone(const LAYER_INFO &aLayerInfo)
Some layers map to KiCad rule areas (zones) - for example a package keepout on ALL maps to a rule are...
static EDA_ANGLE fromMillidegrees(uint32_t aMilliDegrees)
const BLK_T & BlockDataAs(const BLOCK_BASE &aBlock)
#define BLK_FIELD(BLK_T, FIELD)
static const std::unordered_map< LAYER_INFO, PCB_LAYER_ID > s_LayerKiMap
Map of the pre-set class:subclass pairs to standard layers.
static const std::unordered_map< LAYER_INFO, wxString > s_OptionalFixedMappings
Names for custom KiCad layers that correspond to pre-defined Allegro layers.
void BulkAddToBoard(BOARD &aBoard, std::vector< std::unique_ptr< T > > &&aItems)
static uint32_t PadGetNextInFootprint(const BLOCK_BASE &aBlock)
"Get Next" function for the pad list in a footprint's 0x32 list.
LAYER_INFO expectLayerFromBlock(const BLOCK_BASE &aBlock)
Get a layer from a block that has layer info.
static int clampForScale(double aValue)
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
The base class for all blocks in the main body of an Allegro file.
uint8_t GetBlockType() const
const T & GetData() const
VECTOR2I scale(const VECTOR2I &aVector) const
SHAPE_POLY_SET shapeToPolySet(const BLK_0x28_SHAPE &aShape) const
wxString resolveMatchGroupName(const BLK_0x1B_NET &aNet) const
Follow m_MatchGroupPtr through the 0x26/0x2C pointer chain to get the match group name for a NET.
const SHAPE_LINE_CHAIN & buildSegmentChain(uint32_t aStartKey) const
Walk a geometry chain (0x01 arcs and 0x15-17 segments) starting from the given key,...
LAYER_MAPPING_HANDLER m_layerMappingHandler
PROGRESS_REPORTER * m_progressReporter
void reportUnexpectedBlockType(uint8_t aGot, uint8_t aExpected, uint32_t aKey=0, size_t aOffset=0, const wxString &aName=wxEmptyString) const
const BLK_0x07_COMPONENT_INST * getFpInstRef(const BLK_0x2D_FOOTPRINT_INST &aFpInstance) const
Look up 0x07 FP instance data (0x07) for a given 0x2D FP instance.
std::vector< const BLOCK_BASE * > getShapeRelatedBlocks(const BLK_0x28_SHAPE &aShape) const
Get blocks that are related to the BOUNDARY shape, i.e.
VECTOR2I scaleSize(const VECTOR2I &aSize) const
PCB_LAYER_ID getLayer(const LAYER_INFO &aLayerInfo) const
std::unordered_map< uint32_t, SHAPE_LINE_CHAIN > m_segChainCache
std::vector< std::unique_ptr< PCB_SHAPE > > buildShapes(const BLK_0x14_GRAPHIC &aGraphicList, BOARD_ITEM_CONTAINER &aParent)
Build the shapes from an 0x14 shape list.
BOARD_BUILDER(const BRD_DB &aBrdDb, BOARD &aBoard, REPORTER &aReporter, PROGRESS_REPORTER *aProgressReporter, const LAYER_MAPPING_HANDLER &aLayerMappingHandler)
std::unique_ptr< LAYER_MAPPER > m_layerMapper
std::vector< std::unique_ptr< BOARD_ITEM > > buildDrillMarker(const BLK_0x0C_PIN_DEF &aPinDef, BOARD_ITEM_CONTAINER &aParent)
Build a drill marker from a 0x0C PIN_DEF block.
std::unique_ptr< PCB_SHAPE > buildRect(const BLK_0x24_RECT &aRect, BOARD_ITEM_CONTAINER &aParent)
Build a rectangular shape from a 0x24 RECT block.
std::vector< std::unique_ptr< PCB_SHAPE > > buildPolygonShapes(const BLK_0x28_SHAPE &aShape, BOARD_ITEM_CONTAINER &aParent)
Build graphics from an 0x28 SHAPE, with separate items per segment/arc.
std::unique_ptr< PCB_SHAPE > buildArc(const BLK_0x01_ARC &aArc, const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aLayer, BOARD_ITEM_CONTAINER &aParent)
const T * expectBlockByKey(uint32_t aKey, uint8_t aType) const
std::unique_ptr< PCB_TEXT > buildPcbText(const BLK_0x30_STR_WRAPPER &aStrWrapper, BOARD_ITEM_CONTAINER &aParent)
std::unique_ptr< FOOTPRINT > buildFootprint(const BLK_0x2D_FOOTPRINT_INST &aFpInstance)
void reportMissingBlock(uint32_t aKey, uint8_t aType) const
std::unordered_map< uint32_t, NETINFO_ITEM * > m_netCache
std::unique_ptr< ZONE > buildZone(const BLOCK_BASE &aBoundaryBlock, const std::vector< const BLOCK_BASE * > &aRelatedBlocks, ZONE_FILL_HANDLER &aZoneFillHandler)
Build a ZONE from an 0x0E, 0x24 or 0x28 block.
void applyConstraintSets()
SHAPE_LINE_CHAIN buildOutline(const BLK_0x0E_RECT &aRect) const
void applyNetConstraints()
std::unique_ptr< PCB_SHAPE > buildLineSegment(const BLK_0x15_16_17_SEGMENT &aSegment, const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aLayer, BOARD_ITEM_CONTAINER &aParent)
Build a single line segment.
std::vector< std::unique_ptr< BOARD_ITEM > > buildTrack(const BLK_0x05_TRACK &aBlock, int aNetcode)
std::vector< const BLK_0x36_DEF_TABLE::FontDef_X08 * > m_fontDefList
std::unordered_map< uint32_t, ZoneFillEntry > m_zoneFillShapes
SHAPE_POLY_SET tryBuildZoneShape(const BLOCK_BASE &aBlock)
Try to build a zone shape for the given block, with holes.
wxString get0x30StringValue(uint32_t a0x30Key) const
Get just the string value from a 0x31 STRING WRAPPER -> 0x30 STRING GRAPHIC pair.
const BLK_0x36_DEF_TABLE::FontDef_X08 * getFontDef(unsigned aIndex) const
Get the font definition for a given index in a 0x30, etc.
std::vector< std::unique_ptr< BOARD_ITEM > > buildGraphicItems(const BLOCK_BASE &aBlock, BOARD_ITEM_CONTAINER &aParent)
Build a list of graphic items, e.g.
std::unique_ptr< BOARD_ITEM > buildVia(const BLK_0x33_VIA &aBlock, int aNetcode)
void enablePadTeardrops()
std::unique_ptr< PCB_SHAPE > buildPolygon(const BLK_0x28_SHAPE &aShape, BOARD_ITEM_CONTAINER &aParent)
Build a graphic polygon from a 0x28 SHAPE block.
wxString resolveConstraintSetNameFromField(uint32_t aFieldKey) const
Extract constraint set name from a 0x03 FIELD block pointer.
std::unordered_set< uint32_t > m_usedZoneFillShapes
std::vector< std::unique_ptr< BOARD_ITEM > > buildPadItems(const BLK_0x1C_PADSTACK &aPadstack, FOOTPRINT &aFp, const wxString &aPadName, int aNetcode)
Construct "pad" items for a given 0x1C PADSTACK block.
An Allegro database that represents a .brd file (amd presumably .dra)
std::unique_ptr< FILE_HEADER > m_Header
std::optional< std::variant< wxString, uint32_t > > GetOptField(uint16_t aFieldCode) const
Get the raw variant value of the field with the given code, if present.
Class to handle the mapping for Allegro CLASS/SUBCLASS idiom to KiCad layers.
PCB_LAYER_ID GetPlaceBounds(bool aTop)
Allegro puts more graphics than just the polygon on PBT/B, but we don't want to always make a static ...
void FinalizeLayers()
Called after all the custom layers are loaded.
void ProcessLayerList(uint8_t aClass, const BLK_0x2A_LAYER_LIST &aList)
LAYER_MAPPER(const BRD_DB &aRawBoard, BOARD &aBoard, const LAYER_MAPPING_HANDLER &aLayerMappingHandler)
PCB_LAYER_ID addUserLayer(const wxString &aName)
std::unordered_map< LAYER_INFO, wxString > m_customLayerDialogNames
Names used in the layer mapping dialog for custom (non-ETCH, non-static) layers.
static PCB_LAYER_ID getNthUserLayer(int aNum)
std::unordered_map< const BLK_0x2A_LAYER_LIST *, std::vector< CUSTOM_LAYER > > m_Lists
PCB_LAYER_ID mapCustomLayerByName(const wxString &aLayerName)
Create or find a mapped layer with a given name, but not specifically bound to a specific class:subcl...
LSET GetRuleAreaLayers(const LAYER_INFO &aLayerInfo)
std::unordered_map< LAYER_INFO, PCB_LAYER_ID > m_staticLayerOverrides
Overrides for the static s_LayerKiMap entries, populated by the layer mapping handler.
std::unordered_map< wxString, PCB_LAYER_ID > m_MappedOptionalLayers
This is a map of optional, Allegro layers that we have mapped to KiCad layers with given names.
PCB_LAYER_ID GetLayer(const LAYER_INFO &aLayerInfo)
bool IsOutlineLayer(const LAYER_INFO &aLayerInfo) const
Resolve the subclass name for a given class:subclass pair using the per-class custom layer list.
bool IsLayerMapped(PCB_LAYER_ID aLayerId) const
Return whether this layer ID is something we mapped to, or the catch-all unmapped layer.
std::unordered_map< LAYER_INFO, int > m_unknownLayers
A record of what we failed to map.
std::unordered_map< uint8_t, std::vector< CUSTOM_LAYER > * > m_ClassCustomLayerLists
static PCB_LAYER_ID getNthCopperLayer(int aNum, int aTotal)
std::unordered_map< LAYER_INFO, PCB_LAYER_ID > m_customLayerToKiMap
The main map from CLASS:SUBCLASS custom mappings to KiCadLayers.
PCB_LAYER_ID m_unmappedLayer
PCB_LAYER_ID MapCustomLayer(const LAYER_INFO &aLayerInfo, const wxString &aLayerName)
Record a specific class:subclass layer as mapping to some KiCad user layer, with a given name.
const LAYER_MAPPING_HANDLER & m_layerMappingHandler
Priority task dispatcher for zone fills - we want to do the biggest ones first.
COMPLEX_FIRST_FILL_TASK(bool aSimplify)
int computePriorityKey(const FILL_INFO &a) const override
size_t task(FILL_INFO &fillInfo) override
Filled zones have their own outline and the fill itself comes from a bunch of "related" spaces.
void ProcessPolygons(bool aSimplify)
Process the polygons in a thread pool for more fans, more faster.
void QueuePolygonForZone(ZONE &aZone, SHAPE_POLY_SET aFilledArea, PCB_LAYER_ID aLayer)
std::vector< FILL_INFO > m_FillInfos
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void FinalizeBulkAdd(std::vector< BOARD_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
virtual void SetFilled(bool aFlag)
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
iterator(uint32_t aCurrent, uint32_t aTail, const BRD_DB &aBoard, NEXT_FUNC_T aNextFunc)
bool operator!=(const iterator &other) const
const BLOCK_BASE * m_currBlock
const BLOCK_BASE * operator*() const
void SetNextFunc(NEXT_FUNC_T aNextFunc)
std::function< uint32_t(const BLOCK_BASE &)> NEXT_FUNC_T
NEXT_FUNC_T m_nextFunction
LL_WALKER(uint32_t aHead, uint32_t aTail, const BRD_DB &aBoard)
LL_WALKER(const FILE_HEADER::LINKED_LIST &aList, const BRD_DB &aBoard)
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & AllLayersMask()
A collection of nets and the parameters used to route or test these nets.
static const char Default[]
the name of the default NETCLASS
int GetDiffPairGap() const
bool HasDiffPairWidth() const
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
bool HasTrackWidth() const
int GetDiffPairWidth() const
bool HasDiffPairGap() const
int GetTrackWidth() const
bool HasClearance() const
Handle the data for a net.
const wxString & GetNetname() const
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
COPPER_LAYER_PROPS & CopperLayer(PCB_LAYER_ID aLayer)
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
void SetLayerSet(const LSET &aSet)
static LSET PTHMask()
layer set for a through hole pad
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void Execute(ContainerT &aItems)
Call this to execute the task on all items in aItems, using the thread pool and dispatching the tasks...
PRIORITY_THREAD_POOL_TASK()
A small class to help profiling.
double msecs(bool aSinceLast=false)
A progress reporter interface for use in multi-threaded environments.
A pure virtual class used to derive REPORTER objects from.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
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.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
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 ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int TotalVertices() const
Return total number of vertices stored 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)
int AddPolygon(const POLYGON &apolygon)
Adds a polygon to the set.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const POLYGON & CPolygon(int aIndex) const
const std::vector< POLYGON > & CPolygons() const
Simple container to manage line stroke parameters.
Rate-limiter that fires at most once per interval.
const std::string Format() const
Return the vector formatted as a string.
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
SHAPE_POLY_SET * Outline()
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
const int minSize
Push and Shove router track width and via size dialog.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE FULL_CIRCLE
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
static const wxChar *const traceAllegroBuilder
Flag to enable debug output of Allegro board construction.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
#define MAX_USER_DEFINED_LAYERS
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
@ LEFT_RIGHT
Flip left to right (around the Y axis)
@ PHYS_CONSTRAINT_SET
Physical Constraint Set assignment.
std::vector< VECTOR2I > MakeRegularPolygonPoints(const VECTOR2I &aCenter, size_t aN, const VECTOR2I &aPt0)
Get the corners of a regular polygon from the centre, one point and the number of sides.
std::vector< SEG > MakeCrossSegments(const VECTOR2I &aCenter, const VECTOR2I &aSize, EDA_ANGLE aAngle)
Create the two segments for a cross.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ SMD
Smd pad, appears on the solder paste layer (default)
@ PTH
Plated through hole pad.
Class to handle a set of BOARD_ITEMs.
static const wxChar *const traceAllegroPerf
std::function< std::map< wxString, PCB_LAYER_ID >(const std::vector< INPUT_LAYER_DESC > &)> LAYER_MAPPING_HANDLER
Pointer to a function that takes a map of source and KiCad layers and returns a re-mapped version.
Utility functions for working with shapes.
Arc segment used in tracks, zone outlines, and shape boundaries.
uint8_t m_SubType
Bit 6 (0x40) = clockwise direction.
Field/property references with variable-typed substructs.
std::variant< uint32_t, std::array< uint32_t, 2 >, std::string, SUB_0x6C, SUB_0x70_0x74, SUB_0xF6 > m_Substruct
Net assignment linking a net (0x1B) to its member objects.
Component instance reference data.
Pin definition with shape type, drill character, coordinates, and size.
std::array< int32_t, 2 > m_Size
uint32_t GetShape() const
std::array< int32_t, 2 > m_Coords
Pad geometry and placement in board-absolute coordinates.
uint32_t m_Rotation
Board-absolute millidegrees. Subtract footprint rotation for FP-local orientation.
int32_t m_CoordsX
Board coordinates. Use SetFPRelativePosition() for KiCad FP-local space.
int32_t m_CoordsY
Board coordinates. Use SetFPRelativePosition() for KiCad FP-local space.
uint32_t m_Rotation
Rotation in millidegrees.
std::array< int32_t, 4 > m_Coords
Graphics container holding a chain of line segments and arcs.
0x15 , 0x16, 0x17 are segments:
uint32_t m_MatchGroupPtr
Diff pair / match group pointer (0x26 or 0x2C)
Padstack definition containing drill dimensions and a table of per-layer pad/antipad/thermal componen...
size_t m_NumCompsPerLayer
uint32_t GetDrillSize() const
size_t m_NumFixedCompEntries
How many of the entries are fixed roles (after this is n*layers)
std::vector< PADSTACK_COMPONENT > m_Components
Collection of components that make up the padstack.
uint32_t GetLayerCount() const
Physical constraint sets containing trace width, clearance, and routing rules.
uint32_t m_FieldPtr
Pointer to 0x03 FIELD with CS name (fallback when m_NameStrKey fails)
uint32_t m_NameStrKey
String table key for constraint set name.
std::vector< std::array< uint8_t, 56 > > m_DataB
Per-copper-layer dimension values, 14 x int32 per record.
Signal integrity and simulation model data (IBIS netlists).
Per-padstack dimension records with name and value.
Rectangle defined by four coordinates.
uint32_t m_Rotation
Rotation in millidegrees.
std::array< int32_t, 4 > m_Coords
Polygon shape defined by a linked list of segments starting at m_FirstSegmentPtr (0x15/0x16/0x17 line...
uint32_t m_FirstSegmentPtr
uint32_t m_FirstKeepoutPtr
uint32_t GetTablePtr() const
Represents a list of layers.
COND_GE< FMT_VER::V_165, std::vector< REF_ENTRY > > m_RefEntries
COND_LT< FMT_VER::V_165, std::vector< NONREF_ENTRY > > m_NonRefEntries
Lookup table used for named associations.
@ SUBTYPE_GRAPHICAL_GROUP
Used for drill charts and x-section charts.
Connection point at a track junction or pad-to-track transition.
TEXT_ALIGNMENT m_Alignment
Text object with position, rotation, layer, font properties, and alignment.
COND_GE< FMT_VER::V_172, TEXT_PROPERTIES > m_Font
uint32_t m_Rotation
Millidegrees.
COND_LT< FMT_VER::V_172, TEXT_PROPERTIES > m_Font16x
String graphic content holding the actual text value and its display layer category.
Placed pad instance linking a pad definition (0x0D via m_PadPtr) to its parent footprint (m_ParentFp)...
Via instance with board position, padstack reference (m_Padstack for drill/annular ring definitions),...
Heterogeneous definition table containing font metrics (FontDef_X08), layer name definitions (X03),...
std::vector< SubstructVariant > m_Items
Fixed-capacity pointer array (100 entries).
std::array< uint32_t, 100 > m_Ptrs
Ordered list of block keys.
@ ANALYSIS_MEDIUM1_ISOCONTOUR
@ ANALYSIS_PCB_TEMPERATURE
@ BGEOM_SILKSCREEN_BOTTOM
@ PGEOM_SILKSCREEN_BOTTOM
@ ANALYSIS_LOW_ISOCONTOUR
@ BGEOM_SWITCH_AREA_BOTTOM
@ BGEOM_SOLDERMASK_BOTTOM
@ ANALYSIS_MEDIUM3_ISOCONTOUR
@ PGEOM_PLACE_BOUND_BOTTOM
@ ANALYSIS_MEDIUM2_ISOCONTOUR
@ PGEOM_SOLDERMASK_BOTTOM
@ ANALYSIS_HIGH_ISOCONTOUR
@ BGEOM_PLACE_GRID_BOTTOM
Represents the information found in a single entry of a layer list.
std::optional< int > GetNetMinLineWidth() const
Substruct in a padstack object.
uint32_t m_StrPtr
Seems to point to various things:
@ TYPE_CHAMFERED_RECTANGLE
COND_GE< FMT_VER::V_172, int32_t > m_Z1
When processing a view, some objects are available and some are not.
This is all the info needed to do the fill of one layer of one zone.
SHAPE_POLY_SET m_CombinedFill
The wider filled area we will chop a piece out of for this layer of this zone.
The features of a padstack that can vary between copper layers All parameters are optional; leaving t...
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
size_t operator()(const LAYER_INFO &aLayerInfo) const noexcept
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
std::vector< std::unique_ptr< ZONE > > MergeZonesWithSameOutline(std::vector< std::unique_ptr< ZONE > > &&aZones)
Merges zones with identical outlines and nets on different layers into single multi-layer zones.
@ FULL
pads are covered by copper