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 = {
331 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
354 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
378 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
387 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
395 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
413 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
430 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
439 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
443 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
447 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
453 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
477 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
479 if( classIt != s_ClassNames.end() )
480 className = classIt->second;
482 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
484 wxString subclassName;
487 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
489 if( classMapIt != s_SubclassNameMaps.end() )
491 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
493 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
495 if( subIt != subclassMap.end() )
496 subclassName = subIt->second;
500 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
506 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
509 return className + wxS(
"/" ) + subclassName;
548 return trace.m_Layer;
558 return shape.m_Layer;
576 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
578 return layerInfo.value();
610 if(
m_Lists.count( &aList ) == 0 )
612 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
618 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
627 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
637 classLayers.size(), aClass, aList.
m_Key );
659 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
660 const size_t numCuLayers = etchLayers.size();
662 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
664 std::vector<INPUT_LAYER_DESC> inputLayers;
666 for(
size_t li = 0; li < numCuLayers; ++li )
669 desc.
Name = etchLayers[li].m_Name;
673 inputLayers.push_back( desc );
678 int nextAutoUser = 0;
685 for(
size_t si = 0; si < layerList->size(); ++si )
687 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
696 if( layerList->at( si ).m_Name.length() > 0 )
697 desc.
Name = layerList->at( si ).m_Name;
702 inputLayers.push_back( desc );
713 desc.
Name = layerName;
717 inputLayers.push_back( desc );
727 inputLayers.push_back( desc );
733 for(
size_t li = 0; li < numCuLayers; ++li )
736 const wxString& layerName = etchLayers[li].m_Name;
738 auto it = resolvedMapping.find( layerName );
739 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
743 m_board.SetLayerName( lId, layerName );
747 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
751 auto rmIt = resolvedMapping.find( displayName );
762 auto rmIt = resolvedMapping.find( dialogName );
767 m_board.SetLayerName( rmIt->second, dialogName );
772 LSET enabledLayersMask =
m_board.GetEnabledLayers();
774 for(
const auto& [
name, layerId] : resolvedMapping )
777 enabledLayersMask |=
LSET{ layerId };
783 m_board.GetLayerName( layerId ), layerId );
787 m_board.SetEnabledLayers( enabledLayersMask );
789 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
814 && cLayerList == etchIt->second
815 && aLayerInfo.
m_Subclass < cLayerList->size() )
823 if( aLayerInfo.
m_Subclass < cLayerList->size() )
875 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
929 if( aNum == aTotal - 1 )
962 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
963 m_board.SetLayerName( lId, aName );
970 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
1033 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
1036 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
1039 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1052 double result = std::round( aValue );
1054 if(
result > std::numeric_limits<int>::max() )
1055 return std::numeric_limits<int>::max();
1057 if(
result < std::numeric_limits<int>::min() )
1058 return std::numeric_limits<int>::min();
1060 return static_cast<int>(
result );
1089 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1095 const wxString& aName )
const
1097 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1098 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1099 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#lx ", aOffset );
1101 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1112 if( blk0x30 ==
nullptr )
1117 if( blk0x31 ==
nullptr )
1128 bool encountered =
false;
1132 if( block->GetBlockType() != 0x36 )
1137 if( blk0x36.
m_Code != 0x08 )
1148 for(
const auto& item : blk0x36.
m_Items )
1150 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1166 std::vector<BOARD_ITEM*> bulkAdded;
1172 const uint8_t type = block->GetBlockType();
1182 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1187 if( netName.IsEmpty() )
1188 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1190 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1194 bulkAdded.push_back( kiNetInfo.get() );
1198 m_board.FinalizeBulkAdd( bulkAdded );
1208 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1209 return wxEmptyString;
1212 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1215 return wxEmptyString;
1219 size_t sep = str->find(
":\\" );
1221 if( sep == std::string::npos )
1222 return wxEmptyString;
1224 std::string extracted = str->substr( sep + 2 );
1226 if( !extracted.empty() && extracted.back() ==
'\\' )
1227 extracted.pop_back();
1229 return wxString( extracted );
1238 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1247 int diffPairGap = 0;
1251 std::map<wxString, CS_DEF> constraintSets;
1254 std::map<uint32_t, wxString> keyToSetName;
1261 if( block->GetBlockType() != 0x1D )
1269 if( resolved && !resolved->IsEmpty() )
1271 setName = *resolved;
1279 if( setName.IsEmpty() )
1280 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1286 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1291 const auto& record = csBlock.
m_DataB[0];
1293 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1294 memcpy( fields, record.data(),
sizeof( fields ) );
1301 def.lineWidth =
scale( fields[1] );
1302 def.clearance =
scale( fields[4] );
1308 def.lineWidth =
scale( fields[0] );
1309 def.clearance =
scale( fields[1] );
1312 def.diffPairGap =
scale( fields[7] );
1314 constraintSets[setName] = def;
1318 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1319 setName, def.lineWidth, def.clearance, def.diffPairGap );
1322 if( constraintSets.empty() )
1329 for(
const auto& [
name, def] : constraintSets )
1331 wxString ncName =
name;
1334 ncName = wxS(
"Allegro_Default" );
1336 if( netSettings->HasNetclass( ncName ) )
1339 auto nc = std::make_shared<NETCLASS>( ncName );
1341 if( def.lineWidth > 0 )
1342 nc->SetTrackWidth( def.lineWidth );
1344 if( def.clearance > 0 )
1345 nc->SetClearance( def.clearance );
1347 if( def.diffPairGap > 0 )
1349 nc->SetDiffPairGap( def.diffPairGap );
1352 if( def.lineWidth > 0 )
1353 nc->SetDiffPairWidth( def.lineWidth );
1356 netSettings->SetNetclass( ncName, nc );
1362 wxString defaultSetName;
1364 for(
const auto& [
name, def] : constraintSets )
1366 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1368 defaultSetName =
name;
1384 wxString assignedSetName;
1386 if( csField.has_value() )
1388 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1390 auto it = keyToSetName.find( *intVal );
1392 if( it != keyToSetName.end() )
1393 assignedSetName = it->second;
1395 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1397 if( constraintSets.count( *strVal ) )
1398 assignedSetName = *strVal;
1403 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1404 assignedSetName = defaultSetName;
1406 if( assignedSetName.IsEmpty() )
1409 wxString ncName = assignedSetName;
1412 ncName = wxS(
"Allegro_Default" );
1414 if( !netSettings->HasNetclass( ncName ) )
1423 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1424 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1427 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1436 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1440 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1449 if( !minWidth.has_value() || minWidth.value() <= 0 )
1452 int widthNm =
scale( minWidth.value() );
1453 widthToNetKeys[widthNm].push_back( aView.
m_Net->
GetKey() );
1456 if( widthToNetKeys.empty() )
1462 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1464 int widthMils = ( widthNm + 12700 ) / 25400;
1465 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1467 if( netSettings->HasNetclass( ncName ) )
1470 auto nc = std::make_shared<NETCLASS>( ncName );
1471 nc->SetTrackWidth( widthNm );
1472 netSettings->SetNetclass( ncName, nc );
1474 for( uint32_t netKey : netKeys )
1482 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1486 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1487 ncName, widthNm, netKeys.size() );
1490 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1491 widthToNetKeys.size() );
1498 return wxEmptyString;
1503 return wxEmptyString;
1505 uint32_t tableKey = 0;
1511 tableKey = x26.m_GroupPtr;
1518 if(
next &&
next->GetBlockType() == 0x26 )
1521 tableKey = x26b.m_GroupPtr;
1532 return wxEmptyString;
1536 return wxEmptyString;
1542 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1543 return wxEmptyString;
1548 return wxEmptyString;
1552 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1561 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1564 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1567 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1579 if( groupName.empty() )
1582 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1585 if( groupToNetKeys.empty() )
1594 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1598 bool isDiffPair = ( netKeys.size() == 2 );
1599 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1600 wxString ncName = ncPrefix + groupName;
1602 if( netSettings->HasNetclass( ncName ) )
1605 auto nc = std::make_shared<NETCLASS>( ncName );
1609 for( uint32_t netKey : netKeys )
1616 NETCLASS* existing = it->second->GetNetClass();
1636 netSettings->SetNetclass( ncName, nc );
1638 for( uint32_t netKey : netKeys )
1646 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1656 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1657 groupName, ncName, netKeys.size() );
1661 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1662 dpCount, mgCount, groupToNetKeys.size() );
1681 std::unordered_set<LAYER_INFO> layersFound;
1683 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1685 if(
info.has_value() )
1687 layersFound.insert( std::move(
info.value() ) );
1701 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1702 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1703 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1713 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1715 for(
size_t i = 0; i < layerMap.size(); ++i )
1717 const uint8_t classNum =
static_cast<uint8_t
>( i );
1719 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1748 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1752 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1765 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1791 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1792 shape->SetLayer( aLayer );
1793 shape->SetStart( start );
1794 shape->SetEnd(
end );
1797 int adjustedWidth = width;
1799 if( adjustedWidth <= 0 )
1800 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1802 shape->SetWidth( adjustedWidth );
1815 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1817 shape->SetLayer( aLayer );
1822 start.Format(),
end.Format() );
1825 start =
scale( start );
1832 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1838 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1840 shape->SetWidth( arcWidth );
1846 shape->SetCenter( c );
1847 shape->SetRadius(
radius );
1858 EDA_ANGLE angle = endangle - startangle;
1860 if( clockwise && angle <
ANGLE_0 )
1862 if( !clockwise && angle >
ANGLE_0 )
1871 shape->SetArcGeometry( start, mid,
end );
1881 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
1886 text->SetPosition( textPos );
1887 text->SetLayer( layer );
1893 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
1894 "in string wrapper (0x30) with key %#010x",
1902 if( aStrWrapper.
m_Font.has_value() )
1903 props = &aStrWrapper.
m_Font.value();
1905 if( !props && aStrWrapper.
m_Font16x.has_value() )
1911 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
1912 aStrWrapper.
m_Key ),
1928 text->SetTextAngle( textAngle );
1931 text->SetMirrored(
true );
1956 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1958 const uint32_t markerShape = aPinDef.
GetShape();
1964 const auto addLine = [&](
const SEG& aSeg )
1966 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1967 shape->SetStart( aSeg.A );
1968 shape->SetEnd( aSeg.B );
1969 shapes.push_back( std::move( shape ) );
1972 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
1974 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
1975 shape->SetPolyPoints( aPts );
1976 shapes.push_back( std::move( shape ) );
1979 switch( markerShape )
1983 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
1984 shape->SetCenter(
center );
1985 shape->SetRadius( size.x / 2 );
1986 shapes.push_back( std::move( shape ) );
1992 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
1993 shape->SetStart(
center - size / 2 );
1994 shape->SetEnd(
center + size / 2 );
1995 shapes.push_back( std::move( shape ) );
2000 std::unique_ptr<PCB_SHAPE> shape;
2004 for(
const SEG& seg : segs )
2013 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2014 shape->SetStart(
center - size / 2 );
2015 shape->SetEnd(
center + size / 2 );
2017 int minSize = std::min( size.x, size.y );
2018 shape->SetCornerRadius(
minSize / 2 );
2019 shapes.push_back( std::move( shape ) );
2061 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2062 markerShape, aPinDef.
m_Key );
2067 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2068 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2070 shape->SetLayer( layer );
2071 shape->SetWidth( 0 );
2073 items.push_back( std::move( shape ) );
2083 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2096 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2098 newItems.push_back( std::move( shape ) );
2104 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2105 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2106 newItems.push_back( std::move( shape ) );
2112 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2114 newItems.push_back( std::move( shape ) );
2120 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2122 newItems.push_back( std::move( shape ) );
2129 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2131 newItems.push_back( std::move( newItem ) );
2154 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2168 for(
const BLOCK_BASE* segBlock : segWalker )
2170 std::unique_ptr<PCB_SHAPE> shape;
2172 switch( segBlock->GetBlockType() )
2191 segBlock->GetBlockType() );
2197 shapes.push_back( std::move( shape ) );
2206 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2209 shape->SetLayer( layer );
2216 shape->SetStart( cornerA );
2217 shape->SetEnd( cornerB );
2220 shape->Rotate( cornerA, angle );
2222 const int lineWidth = 0;
2223 shape->SetWidth( lineWidth );
2231 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2234 shape->SetLayer( layer );
2241 shape->SetStart( cornerA );
2242 shape->SetEnd( cornerB );
2245 shape->Rotate( cornerA, angle );
2247 const int lineWidth = 0;
2248 shape->SetWidth( lineWidth );
2256 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2259 shape->SetLayer( layer );
2265 if(
chain.PointCount() < 3 )
2267 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2272 chain.SetClosed(
true );
2273 shape->SetPolyShape(
chain );
2275 const int lineWidth = 0;
2276 shape->SetWidth( lineWidth );
2285 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2292 for(
const BLOCK_BASE* segBlock : segWalker )
2294 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2295 shape->SetLayer( layer );
2296 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2298 switch( segBlock->GetBlockType() )
2312 shape->SetCenter( c );
2313 shape->SetRadius(
radius );
2319 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2327 EDA_ANGLE angle = endangle - startangle;
2329 if( clockwise && angle <
ANGLE_0 )
2332 if( !clockwise && angle >
ANGLE_0 )
2338 shape->SetArcGeometry( start, mid,
end );
2351 shape->SetStart( start );
2352 shape->SetEnd(
end );
2353 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2357 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2361 shapes.push_back( std::move( shape ) );
2370 uint32_t refKey = 0x00;
2388 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2394 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2396 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
m_LayerCount );
2399 std::optional<int> thermalGap;
2401 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2420 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2427 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2433 auto& layerCuProps = copperLayers[i];
2435 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2469 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.
value() / (double) minDim;
2471 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2484 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.
value() / (double) minDim;
2486 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2498 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2512 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2513 padStackName, i, padComp.
m_StrPtr );
2528 int anchorSize =
static_cast<int>(
2531 if( anchorSize < 1 )
2534 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2536 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2538 poly->SetFilled(
true );
2539 poly->SetWidth( 0 );
2540 layerCuProps->custom_shapes.push_back( poly );
2545 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2557 const int w = std::max( padComp.
m_W, 300 );
2558 const int h = std::max( padComp.
m_H, 220 );
2561 auto S = [&](
int x,
int y )
2567 outline.
Append(
S( 0, -h / 2 ) );
2568 outline.
Append(
S( w / 2, -h / 6 ) );
2569 outline.
Append(
S( w / 3, h / 2 ) );
2570 outline.
Append(
S( -w / 3, h / 2 ) );
2571 outline.
Append(
S( -w / 2, -h / 6 ) );
2575 int anchorSize =
static_cast<int>(
2578 if( anchorSize < 1 )
2581 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2583 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2585 poly->SetFilled(
true );
2586 poly->SetWidth( 0 );
2587 layerCuProps->custom_shapes.push_back( poly );
2592 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2593 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2603 "differs from pad shape %d",
2607 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2608 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2610 if( clearanceX && clearanceX != clearanceY )
2613 "clearance X=%d Y=%d",
2614 padStackName, i, clearanceX, clearanceY );
2617 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2621 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2624 layerCuProps->clearance = clearanceX;
2633 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2640 "Padstack %s: thermal relief type=%d, gap=%snm",
2641 padStackName, thermalComp.
m_Type,
2642 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2643 : wxString(
"N/A" ) );
2653 if( copperLayers.size() == 0 )
2659 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2662 for(
size_t i = aFrom + 1; i < aTo; ++i )
2664 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2673 for(
size_t i = 0; i < copperLayers.size(); ++i )
2675 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2680 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2685 layerProps = *copperLayers.front();
2687 else if( copperLayers.front() && copperLayers.back()
2688 && layersEqual( 1, copperLayers.size() - 1 ) )
2690 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2696 if( copperLayers.size() > 2 && copperLayers[1] )
2704 for(
size_t i = 0; i < copperLayers.size(); ++i )
2706 if( !copperLayers[i] )
2713 else if( i == copperLayers.size() - 1 )
2742 int slotX =
scale(
static_cast<int>( slotArr[0] ) );
2743 int slotY =
scale(
static_cast<int>( slotArr[3] ) );
2745 if( slotX > 0 && slotY > 0 )
2760 drillW =
scale(
static_cast<int>( aPadstack.
m_Drill ) );
2776 bool drillIsTaller = ( drillH > drillW );
2778 if( padIsTaller != drillIsTaller )
2779 std::swap( drillW, drillH );
2782 bool isSmd = ( drillW == 0 ) || ( aPadstack.
m_LayerCount == 1 );
2792 if( drillW != drillH )
2798 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2799 pad->SetPadstack( padStack );
2800 pad->SetNumber( aPadName );
2801 pad->SetNetCode( aNetcode );
2814 if( thermalGap.has_value() )
2815 pad->SetThermalGap( thermalGap.value() );
2817 padItems.push_back( std::move(
pad ) );
2833 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2834 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2843 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
2854 if( refDesStr.IsEmpty() )
2857 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
2864 fp->SetReference( refDesStr );
2872 fp->SetPosition( fpPos );
2873 fp->SetOrientation( rotation );
2885 const auto canonicalizeLayer = [](
BOARD_ITEM* aItem )
2888 aItem->SetLayer(
FlipLayer( aItem->GetLayer() ) );
2893 for(
const BLOCK_BASE* graphicsBlock : graphicsWalker )
2895 const uint8_t type = graphicsBlock->GetBlockType();
2901 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
2903 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2905 canonicalizeLayer( shape.get() );
2906 fp->Add( shape.release() );
2911 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", type ),
2916 bool valueFieldSet =
false;
2920 for(
const BLOCK_BASE* textBlock : textWalker )
2922 const uint8_t type = textBlock->GetBlockType();
2934 canonicalizeLayer(
text.get() );
2936 const uint8_t textClass = strWrapper.m_Layer.m_Class;
2937 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
2950 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
2951 text->SetText( wxString(
"UNK" ) +
text->GetText() );
2959 field->
SetText( wxS(
"${REFERENCE}" ) );
2965 if( !valueFieldSet )
2971 valueFieldSet =
true;
3006 fp->Add(
text.release() );
3013 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3015 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3017 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3019 canonicalizeLayer( item.get() );
3020 fp->Add( item.release() );
3026 for(
const BLOCK_BASE* areaBlock : areaWalker )
3028 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3030 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3032 canonicalizeLayer( item.get() );
3033 fp->Add( item.release() );
3040 for(
const BLOCK_BASE* padBlock : padWalker )
3048 if( !netAssignment || !padInfo )
3057 const int netCode = ( netIt !=
m_netCache.end() ) ? netIt->second->GetNetCode()
3067 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3069 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3073 PAD*
pad =
static_cast<PAD*
>( item.get() );
3074 pad->SetFPRelativeOrientation( padLocalRot );
3077 item->SetFPRelativePosition( padLocalPos );
3078 fp->Add( item.release() );
3090 if( aFpInstance.
m_Layer != 0 )
3092 fp->SetOrientation( -rotation -
ANGLE_180 );
3101 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3107 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3117 const uint8_t segType = block->GetBlockType();
3130 int width =
static_cast<int>( segInfo.
m_Width );
3132 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3134 seg->SetNetCode( aNetCode );
3135 seg->SetLayer( layer );
3137 seg->SetStart(
scale( start ) );
3139 seg->SetWidth(
scale( width ) );
3141 items.push_back( std::move( seg ) );
3151 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3153 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3160 EDA_ANGLE angle = endAngle - startAngle;
3162 if( clockwise && angle <
ANGLE_0 )
3165 if( !clockwise && angle >
ANGLE_0 )
3171 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3173 arc->SetNetCode( aNetCode );
3174 arc->SetLayer( layer );
3176 arc->SetStart( start );
3179 arc->SetWidth( width );
3181 items.push_back( std::move( arc ) );
3202 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3203 via->SetPosition(
scale( viaPos ) );
3204 via->SetNetCode( aNetCode );
3229 viaDrill =
scale(
static_cast<int>( viaPadstack->
m_Drill ) );
3233 viaDrill = viaWidth / 2;
3234 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack, using fallback %d",
3240 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d) has no valid pad component, using drill-based fallback",
3242 viaWidth = viaDrill * 2;
3245 via->SetWidth(
F_Cu, viaWidth );
3246 via->SetDrill( viaDrill );
3256 std::vector<BOARD_ITEM*> newItems;
3262 const uint8_t type = block->GetBlockType();
3276 const int netCode = netIt->second->GetNetCode();
3279 for(
const BLOCK_BASE* assignBlock : assignmentWalker )
3281 if( assignBlock->GetBlockType() != 0x04 )
3291 for(
const BLOCK_BASE* connItemBlock : connWalker )
3293 const uint8_t connType = connItemBlock->GetBlockType();
3297 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3306 newItemList =
buildTrack( trackData, netCode );
3312 newItemList.push_back(
buildVia( viaData, netCode ) );
3343 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3345 newItems.push_back( newItem.get() );
3352 m_board.FinalizeBulkAdd( newItems );
3354 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3366 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3372 switch( block->GetBlockType() )
3383 newItems.push_back( std::move( rectShape ) );
3396 for(
auto& shapeItem : shapeItems )
3397 newItems.push_back( std::move( shapeItem ) );
3402 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3412 for(
const BLOCK_BASE* block : outline2Walker )
3417 const auto shouldSkip = [](
const LAYER_INFO& aLayer ) ->
bool
3422 switch( block->GetBlockType() )
3428 if( shouldSkip( rectData.
m_Layer ) )
3432 newItems.push_back( std::move( rectShape ) );
3439 if( shouldSkip( rectData.
m_Layer ) )
3443 newItems.push_back( std::move( rectShape ) );
3450 if( shouldSkip( shapeData.
m_Layer ) )
3455 for(
auto& shapeItem : shapeItems )
3456 newItems.push_back( std::move( shapeItem ) );
3461 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3471 for(
const BLOCK_BASE* block : graphicContainerWalker )
3475 switch( block->GetBlockType() )
3481 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3483 for(
auto& item : graphicItems )
3484 newItems.push_back( std::move( item ) );
3489 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in graphic container walker: %#04x",
3490 block->GetBlockType() );
3498 std::vector<BOARD_ITEM*> addedItems;
3499 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3501 addedItems.push_back( item.get() );
3505 m_board.FinalizeBulkAdd( addedItems );
3516 return cacheIt->second;
3519 uint32_t currentKey = aStartKey;
3522 static constexpr int MAX_CHAIN_LENGTH = 50000;
3525 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3546 outline.
Append( shapeArc );
3550 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3557 EDA_ANGLE arcAngle = endAngle - startAngle;
3559 if( clockwise && arcAngle <
ANGLE_0 )
3562 if( !clockwise && arcAngle >
ANGLE_0 )
3569 outline.
Append( shapeArc );
3572 currentKey = arc.m_Next;
3588 currentKey = seg.m_Next;
3607 VECTOR2I topRight{ botRight.x, topLeft.
y };
3608 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3610 outline.
Append( topLeft );
3611 outline.
Append( topRight );
3612 outline.
Append( botRight );
3613 outline.
Append( botLeft );
3625 VECTOR2I topRight{ botRight.x, topLeft.
y };
3626 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3628 outline.
Append( topLeft );
3629 outline.
Append( topRight );
3630 outline.
Append( botRight );
3631 outline.
Append( botLeft );
3642 for(
const BLOCK_BASE* segBlock : segWalker )
3644 switch( segBlock->GetBlockType() )
3656 outline.
Append( shapeArc );
3660 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3667 EDA_ANGLE arcAngle = endAngle - startAngle;
3669 if( clockwise && arcAngle <
ANGLE_0 )
3672 if( !clockwise && arcAngle >
ANGLE_0 )
3679 outline.
Append( shapeArc );
3700 segBlock->GetBlockType() );
3726 while( holeKey != 0 )
3740 polySet.
AddHole( holeOutline );
3743 holeKey = keepout.m_Next;
3761 chain.SetClosed(
true );
3771 chain.SetClosed(
true );
3792 LSET layerSet{ aDefault };
3812 wxLogTrace(
traceAllegroBuilder,
" Unhandled keepout layer subclass %#02x, using default layers",
3824 wxLogTrace(
traceAllegroBuilder,
" Unhandled keepin layer subclass %#02x, using default layers",
3829 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
3915 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ), timer.
msecs() );
3920 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
3929 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
3962 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
3971 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
3976 auto zone = std::make_unique<ZONE>( &
m_board );
3981 zone->SetLayer( layer );
3994 zone->SetIsRuleArea(
true );
3995 zone->SetLayerSet( layerSet );
3996 zone->SetDoNotAllowTracks( isRouteKeepout );
3997 zone->SetDoNotAllowVias( isViaKeepout );
3998 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
3999 zone->SetDoNotAllowPads(
false );
4000 zone->SetDoNotAllowFootprints( isPackageKeepout );
4006 zone->SetZoneName(
"Route Keepin" );
4007 else if( isPackageKeepin )
4008 zone->SetZoneName(
"Package Keepin" );
4013 for(
const BLOCK_BASE* block : aRelatedBlocks )
4018 switch( block->GetBlockType() )
4022 const auto it =
m_netCache.find( block->GetKey() );
4027 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
4029 netCode = it->second->GetNetCode();
4033 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
4034 block->GetKey(), aBoundaryBlock.
GetKey() ),
4044 combinedFill.
Append( fillPolySet );
4054 zone->SetNetCode( netCode );
4060 if( isCopperZone && !combinedFill.
IsEmpty() )
4074 zone->SetIsFilled(
true );
4075 zone->SetNeedRefill(
false );
4088 std::vector<const BLOCK_BASE*> ret;
4089 uint32_t ptr7Key = 0;
4106 if( !ptrArray || ptrArray->
m_Count == 0 )
4109 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4110 ret.resize( count );
4112 for(
size_t i = 0; i < count; i++ )
4126 if( block->GetBlockType() != 0x30 )
4129 const auto& strWrapper =
4139 if( strWrapper.GetGroupPtr() != 0 )
4147 text->GetPosition().x,
text->GetPosition().y );
4157template <std::derived_from<BOARD_ITEM> T>
4160 std::vector<BOARD_ITEM*> rawPointers;
4161 rawPointers.reserve( aItems.size() );
4163 for( std::unique_ptr<T>& item : aItems )
4165 rawPointers.push_back( item.get() );
4177 std::vector<std::unique_ptr<ZONE>> boundaryZones;
4178 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4188 if( block->GetBlockType() != 0x28 )
4201 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ),
4205 boundaryZones.push_back( std::move( zone ) );
4212 for(
const BLOCK_BASE* block : keepoutWalker )
4214 std::unique_ptr<ZONE> zone;
4216 switch( block->GetBlockType() )
4228 zone =
buildZone( *block, {}, zoneFillHandler );
4241 zone =
buildZone( *block, {}, zoneFillHandler );
4250 keepoutZones.push_back( std::move( zone ) );
4257 int keepoutCount = keepoutZones.size();
4258 int boundaryCount = boundaryZones.size();
4265 int mergedCount = mergedZones.size();
4270 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines (%d merged away), %d keepout areas", mergedCount,
4271 boundaryCount - mergedCount, keepoutCount );
4282 if( block->GetBlockType() != 0x2C )
4295 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4299 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4301 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4310 switch( keyTable->GetBlockType() )
4317 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4319 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4321 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4323 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4338 newItems.push_back( std::move( newItem ) );
4355 keyTable->GetBlockType() );
4361 if( newItems.size() > 0 )
4363 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4365 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4366 group->SetName( tableName );
4368 for(
const auto& item : newItems )
4369 group->AddItem( item.get() );
4371 newItems.push_back( std::move(
group ) );
4394 int copperShapeCount = 0;
4395 int teardropCount = 0;
4410 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4412 if( isDynCopperShape )
4414 auto zone = std::make_unique<ZONE>( &
m_board );
4417 zone->SetLayer( fill.layer );
4418 zone->SetNetCode( fill.netCode );
4419 zone->SetLocalClearance( 0 );
4425 zone->AddPolygon(
chain );
4427 zone->SetFilledPolysList( fill.layer, fractured );
4428 zone->SetIsFilled(
true );
4429 zone->SetNeedRefill(
false );
4430 zone->CalculateFilledArea();
4438 shape->SetPolyShape( fractured );
4439 shape->SetFilled(
true );
4440 shape->SetLayer( fill.layer );
4441 shape->SetNetCode( fill.netCode );
4450 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4451 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4457 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4461 if( zone->IsTeardropArea() )
4462 teardropsByNet[zone->GetNetCode()].push_back( zone );
4465 if( teardropsByNet.empty() )
4473 for(
PAD*
pad : fp->Pads() )
4475 auto it = teardropsByNet.find(
pad->GetNetCode() );
4477 if( it == teardropsByNet.end() )
4480 for(
ZONE* tdZone : it->second )
4487 pad->SetTeardropsEnabled(
true );
4501 auto it = teardropsByNet.find(
via->GetNetCode() );
4503 if( it == teardropsByNet.end() )
4506 for(
ZONE* tdZone : it->second )
4513 via->SetTeardropsEnabled(
true );
4520 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4528 static_cast<int>(
m_brdDb.m_FmtVer ),
4531 m_brdDb.m_Header->m_AllegroVersion.data() );
4604 std::vector<BOARD_ITEM*> bulkAddedItems;
4606 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4608 for(
const BLOCK_BASE* fpContainer : fpWalker )
4610 if( fpContainer->GetBlockType() == 0x2B )
4617 for(
const BLOCK_BASE* instBlock : instWalker )
4619 if( instBlock->GetBlockType() != 0x2D )
4622 wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4623 instBlock->GetBlockType(), fpBlock.
m_Key ),
4635 bulkAddedItems.push_back( fp.get() );
4641 wxString::Format(
"Failed to construct footprint for 0x2D key %#010x",
4653 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4654 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4656 if( !bulkAddedItems.empty() )
4657 m_board.FinalizeBulkAdd( bulkAddedItems );
static LSET getRuleAreaLayers(const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aDefault)
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...
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...
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 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 SMDMask()
layer set for a SMD pad on Front layer
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.
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.
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
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
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.
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
@ TOP_BOTTOM
Flip top to bottom (around the X 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)
@ 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...
std::array< uint32_t, 8 > m_DrillArr
In >= V172, elements [4] and [7] hold drill dimensions: [4] = drill diameter (or width for oblong dri...
size_t m_NumCompsPerLayer
uint32_t m_Drill
In < V172, this is the drill diameter in internal coordinates.
COND_GE< FMT_VER::V_172, std::array< uint32_t, 28 > > m_SlotAndUnknownArr
In V172+, elements [0] and [3] hold the true slot outline dimensions (X, Y) in internal coordinate un...
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.
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...
COND_LT< FMT_VER::V_172, uint32_t > m_Ptr7_16x
COND_GE< FMT_VER::V_172, uint32_t > m_Ptr7
uint32_t m_FirstSegmentPtr
uint32_t m_FirstKeepoutPtr
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:
COND_GE< FMT_VER::V_172, int16_t > m_Z1
@ TYPE_CHAMFERED_RECTANGLE
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_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