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;
552 return trace.m_Layer;
562 return shape.m_Layer;
580 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
582 return layerInfo.value();
614 if(
m_Lists.count( &aList ) == 0 )
616 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
622 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
631 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
641 classLayers.size(), aClass, aList.
m_Key );
663 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
664 const size_t numCuLayers = etchLayers.size();
666 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
668 std::vector<INPUT_LAYER_DESC> inputLayers;
670 for(
size_t li = 0; li < numCuLayers; ++li )
673 desc.
Name = etchLayers[li].m_Name;
677 inputLayers.push_back( desc );
682 int nextAutoUser = 0;
689 for(
size_t si = 0; si < layerList->size(); ++si )
691 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
700 if( layerList->at( si ).m_Name.length() > 0 )
701 desc.
Name = layerList->at( si ).m_Name;
706 inputLayers.push_back( desc );
717 desc.
Name = layerName;
721 inputLayers.push_back( desc );
731 inputLayers.push_back( desc );
737 for(
size_t li = 0; li < numCuLayers; ++li )
740 const wxString& layerName = etchLayers[li].m_Name;
742 auto it = resolvedMapping.find( layerName );
743 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
747 m_board.SetLayerName( lId, layerName );
751 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
755 auto rmIt = resolvedMapping.find( displayName );
766 auto rmIt = resolvedMapping.find( dialogName );
771 m_board.SetLayerName( rmIt->second, dialogName );
776 LSET enabledLayersMask =
m_board.GetEnabledLayers();
778 for(
const auto& [
name, layerId] : resolvedMapping )
781 enabledLayersMask |=
LSET{ layerId };
787 m_board.GetLayerName( layerId ), layerId );
791 m_board.SetEnabledLayers( enabledLayersMask );
793 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
818 && cLayerList == etchIt->second
819 && aLayerInfo.
m_Subclass < cLayerList->size() )
827 if( aLayerInfo.
m_Subclass < cLayerList->size() )
879 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
967 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
981 if( aNum == aTotal - 1 )
1014 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
1015 m_board.SetLayerName( lId, aName );
1022 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
1085 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
1088 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
1091 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1174 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1184 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1199 double result = std::round( aValue );
1201 if(
result > std::numeric_limits<int>::max() )
1202 return std::numeric_limits<int>::max();
1204 if(
result < std::numeric_limits<int>::min() )
1205 return std::numeric_limits<int>::min();
1207 return static_cast<int>(
result );
1242 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1248 const wxString& aName )
const
1250 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1251 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1252 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#lx ", aOffset );
1254 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1265 if( blk0x30 ==
nullptr )
1270 if( blk0x31 ==
nullptr )
1281 bool encountered =
false;
1285 if( block->GetBlockType() != 0x36 )
1290 if( blk0x36.
m_Code != 0x08 )
1301 for(
const auto& item : blk0x36.
m_Items )
1303 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1319 std::vector<BOARD_ITEM*> bulkAdded;
1325 const uint8_t type = block->GetBlockType();
1335 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1340 if( netName.IsEmpty() )
1341 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1343 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1347 bulkAdded.push_back( kiNetInfo.get() );
1351 m_board.FinalizeBulkAdd( bulkAdded );
1361 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1362 return wxEmptyString;
1365 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1368 return wxEmptyString;
1372 size_t sep = str->find(
":\\" );
1374 if( sep == std::string::npos )
1375 return wxEmptyString;
1377 std::string extracted = str->substr( sep + 2 );
1379 if( !extracted.empty() && extracted.back() ==
'\\' )
1380 extracted.pop_back();
1382 return wxString( extracted );
1391 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1400 int diffPairGap = 0;
1404 std::map<wxString, CS_DEF> constraintSets;
1407 std::map<uint32_t, wxString> keyToSetName;
1414 if( block->GetBlockType() != 0x1D )
1422 if( resolved && !resolved->IsEmpty() )
1424 setName = *resolved;
1432 if( setName.IsEmpty() )
1433 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1439 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1444 const auto& record = csBlock.
m_DataB[0];
1446 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1447 memcpy( fields, record.data(),
sizeof( fields ) );
1454 def.lineWidth =
scale( fields[1] );
1455 def.clearance =
scale( fields[4] );
1461 def.lineWidth =
scale( fields[0] );
1462 def.clearance =
scale( fields[1] );
1465 def.diffPairGap =
scale( fields[7] );
1467 constraintSets[setName] = def;
1471 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1472 setName, def.lineWidth, def.clearance, def.diffPairGap );
1475 if( constraintSets.empty() )
1482 for(
const auto& [
name, def] : constraintSets )
1484 wxString ncName =
name;
1487 ncName = wxS(
"Allegro_Default" );
1489 if( netSettings->HasNetclass( ncName ) )
1492 auto nc = std::make_shared<NETCLASS>( ncName );
1494 if( def.lineWidth > 0 )
1495 nc->SetTrackWidth( def.lineWidth );
1497 if( def.clearance > 0 )
1498 nc->SetClearance( def.clearance );
1500 if( def.diffPairGap > 0 )
1502 nc->SetDiffPairGap( def.diffPairGap );
1505 if( def.lineWidth > 0 )
1506 nc->SetDiffPairWidth( def.lineWidth );
1509 netSettings->SetNetclass( ncName, nc );
1515 wxString defaultSetName;
1517 for(
const auto& [
name, def] : constraintSets )
1519 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1521 defaultSetName =
name;
1537 wxString assignedSetName;
1539 if( csField.has_value() )
1541 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1543 auto it = keyToSetName.find( *intVal );
1545 if( it != keyToSetName.end() )
1546 assignedSetName = it->second;
1548 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1550 if( constraintSets.count( *strVal ) )
1551 assignedSetName = *strVal;
1556 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1557 assignedSetName = defaultSetName;
1559 if( assignedSetName.IsEmpty() )
1562 wxString ncName = assignedSetName;
1565 ncName = wxS(
"Allegro_Default" );
1567 if( !netSettings->HasNetclass( ncName ) )
1576 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1577 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1580 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1589 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1593 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1602 if( !minWidth.has_value() || minWidth.value() <= 0 )
1605 int widthNm =
scale( minWidth.value() );
1606 widthToNetKeys[widthNm].push_back( aView.
m_Net->
GetKey() );
1609 if( widthToNetKeys.empty() )
1615 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1617 int widthMils = ( widthNm + 12700 ) / 25400;
1618 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1620 if( netSettings->HasNetclass( ncName ) )
1623 auto nc = std::make_shared<NETCLASS>( ncName );
1624 nc->SetTrackWidth( widthNm );
1625 netSettings->SetNetclass( ncName, nc );
1627 for( uint32_t netKey : netKeys )
1635 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1639 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1640 ncName, widthNm, netKeys.size() );
1643 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1644 widthToNetKeys.size() );
1651 return wxEmptyString;
1656 return wxEmptyString;
1658 uint32_t tableKey = 0;
1664 tableKey = x26.m_GroupPtr;
1671 if(
next &&
next->GetBlockType() == 0x26 )
1674 tableKey = x26b.m_GroupPtr;
1685 return wxEmptyString;
1689 return wxEmptyString;
1695 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1696 return wxEmptyString;
1701 return wxEmptyString;
1705 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1714 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1717 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1720 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1732 if( groupName.empty() )
1735 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1738 if( groupToNetKeys.empty() )
1747 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1751 bool isDiffPair = ( netKeys.size() == 2 );
1752 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1753 wxString ncName = ncPrefix + groupName;
1755 if( netSettings->HasNetclass( ncName ) )
1758 auto nc = std::make_shared<NETCLASS>( ncName );
1762 for( uint32_t netKey : netKeys )
1769 NETCLASS* existing = it->second->GetNetClass();
1789 netSettings->SetNetclass( ncName, nc );
1791 for( uint32_t netKey : netKeys )
1799 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1809 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1810 groupName, ncName, netKeys.size() );
1814 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1815 dpCount, mgCount, groupToNetKeys.size() );
1834 std::unordered_set<LAYER_INFO> layersFound;
1836 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1838 if(
info.has_value() )
1840 layersFound.insert( std::move(
info.value() ) );
1854 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1855 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1856 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1866 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1868 for(
size_t i = 0; i < layerMap.size(); ++i )
1870 const uint8_t classNum =
static_cast<uint8_t
>( i );
1872 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1901 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1905 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1918 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1944 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1945 shape->SetLayer( aLayer );
1946 shape->SetStart( start );
1947 shape->SetEnd(
end );
1950 int adjustedWidth = width;
1952 if( adjustedWidth <= 0 )
1953 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1955 shape->SetWidth( adjustedWidth );
1968 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1970 shape->SetLayer( aLayer );
1975 start.Format(),
end.Format() );
1978 start =
scale( start );
1985 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1991 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1993 shape->SetWidth( arcWidth );
1999 shape->SetCenter( c );
2000 shape->SetRadius(
radius );
2011 EDA_ANGLE angle = endangle - startangle;
2013 if( clockwise && angle <
ANGLE_0 )
2015 if( !clockwise && angle >
ANGLE_0 )
2024 shape->SetArcGeometry( start, mid,
end );
2034 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
2037 text->SetLayer( layer );
2043 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
2044 "in string wrapper (0x30) with key %#010x",
2052 if( aStrWrapper.
m_Font.has_value() )
2053 props = &aStrWrapper.
m_Font.value();
2055 if( !props && aStrWrapper.
m_Font16x.has_value() )
2061 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
2062 aStrWrapper.
m_Key ),
2078 text->SetTextAngle( textAngle );
2087 text->SetPosition( textPos + textFontOffset );
2090 text->SetMirrored(
true );
2115 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2117 const uint32_t markerShape = aPinDef.
GetShape();
2123 const auto addLine = [&](
const SEG& aSeg )
2125 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
2126 shape->SetStart( aSeg.A );
2127 shape->SetEnd( aSeg.B );
2128 shapes.push_back( std::move( shape ) );
2131 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
2133 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
2134 shape->SetPolyPoints( aPts );
2135 shapes.push_back( std::move( shape ) );
2138 switch( markerShape )
2142 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
2143 shape->SetCenter(
center );
2144 shape->SetRadius( size.x / 2 );
2145 shapes.push_back( std::move( shape ) );
2151 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2152 shape->SetStart(
center - size / 2 );
2153 shape->SetEnd(
center + size / 2 );
2154 shapes.push_back( std::move( shape ) );
2159 std::unique_ptr<PCB_SHAPE> shape;
2163 for(
const SEG& seg : segs )
2172 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2173 shape->SetStart(
center - size / 2 );
2174 shape->SetEnd(
center + size / 2 );
2176 int minSize = std::min( size.x, size.y );
2177 shape->SetCornerRadius(
minSize / 2 );
2178 shapes.push_back( std::move( shape ) );
2220 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2221 markerShape, aPinDef.
m_Key );
2226 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2227 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2229 shape->SetLayer( layer );
2230 shape->SetWidth( 0 );
2232 items.push_back( std::move( shape ) );
2242 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2255 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2257 newItems.push_back( std::move( shape ) );
2263 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2264 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2265 newItems.push_back( std::move( shape ) );
2271 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2273 newItems.push_back( std::move( shape ) );
2279 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2281 newItems.push_back( std::move( shape ) );
2288 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2290 newItems.push_back( std::move( newItem ) );
2313 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2327 for(
const BLOCK_BASE* segBlock : segWalker )
2329 std::unique_ptr<PCB_SHAPE> shape;
2331 switch( segBlock->GetBlockType() )
2350 segBlock->GetBlockType() );
2356 shapes.push_back( std::move( shape ) );
2365 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2368 shape->SetLayer( layer );
2375 shape->SetStart( cornerA );
2376 shape->SetEnd( cornerB );
2379 shape->Rotate( cornerA, angle );
2381 const int lineWidth = 0;
2382 shape->SetWidth( lineWidth );
2390 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2393 shape->SetLayer( layer );
2400 shape->SetStart( cornerA );
2401 shape->SetEnd( cornerB );
2404 shape->Rotate( cornerA, angle );
2406 const int lineWidth = 0;
2407 shape->SetWidth( lineWidth );
2415 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2418 shape->SetLayer( layer );
2424 if(
chain.PointCount() < 3 )
2426 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2431 chain.SetClosed(
true );
2432 shape->SetPolyShape(
chain );
2434 const int lineWidth = 0;
2435 shape->SetWidth( lineWidth );
2444 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2451 for(
const BLOCK_BASE* segBlock : segWalker )
2453 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2454 shape->SetLayer( layer );
2455 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2457 switch( segBlock->GetBlockType() )
2471 shape->SetCenter( c );
2472 shape->SetRadius(
radius );
2478 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2486 EDA_ANGLE angle = endangle - startangle;
2488 if( clockwise && angle <
ANGLE_0 )
2491 if( !clockwise && angle >
ANGLE_0 )
2497 shape->SetArcGeometry( start, mid,
end );
2510 shape->SetStart( start );
2511 shape->SetEnd(
end );
2512 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2516 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2520 shapes.push_back( std::move( shape ) );
2529 uint32_t refKey = 0x00;
2547 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2553 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2555 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
m_LayerCount );
2558 std::optional<int> thermalGap;
2560 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2579 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2586 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2592 auto& layerCuProps = copperLayers[i];
2594 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2628 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.
value() / (double) minDim;
2630 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2643 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.
value() / (double) minDim;
2645 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2657 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2671 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2672 padStackName, i, padComp.
m_StrPtr );
2687 int anchorSize =
static_cast<int>(
2690 if( anchorSize < 1 )
2693 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2695 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2697 poly->SetFilled(
true );
2698 poly->SetWidth( 0 );
2699 layerCuProps->custom_shapes.push_back( poly );
2704 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2716 const int w = std::max( padComp.
m_W, 300 );
2717 const int h = std::max( padComp.
m_H, 220 );
2720 auto S = [&](
int x,
int y )
2726 outline.
Append(
S( 0, -h / 2 ) );
2727 outline.
Append(
S( w / 2, -h / 6 ) );
2728 outline.
Append(
S( w / 3, h / 2 ) );
2729 outline.
Append(
S( -w / 3, h / 2 ) );
2730 outline.
Append(
S( -w / 2, -h / 6 ) );
2734 int anchorSize =
static_cast<int>(
2737 if( anchorSize < 1 )
2740 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2742 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2744 poly->SetFilled(
true );
2745 poly->SetWidth( 0 );
2746 layerCuProps->custom_shapes.push_back( poly );
2751 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2752 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2762 "differs from pad shape %d",
2766 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2767 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2769 if( clearanceX && clearanceX != clearanceY )
2772 "clearance X=%d Y=%d",
2773 padStackName, i, clearanceX, clearanceY );
2776 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2780 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2783 layerCuProps->clearance = clearanceX;
2792 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2799 "Padstack %s: thermal relief type=%d, gap=%snm",
2800 padStackName, thermalComp.
m_Type,
2801 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2802 : wxString(
"N/A" ) );
2812 if( copperLayers.size() == 0 )
2818 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2821 for(
size_t i = aFrom + 1; i < aTo; ++i )
2823 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2832 for(
size_t i = 0; i < copperLayers.size(); ++i )
2834 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2839 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2844 layerProps = *copperLayers.front();
2846 else if( copperLayers.front() && copperLayers.back()
2847 && layersEqual( 1, copperLayers.size() - 1 ) )
2849 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2855 if( copperLayers.size() > 2 && copperLayers[1] )
2863 for(
size_t i = 0; i < copperLayers.size(); ++i )
2865 if( !copperLayers[i] )
2872 else if( i == copperLayers.size() - 1 )
2901 int slotX =
scale(
static_cast<int>( slotArr[0] ) );
2902 int slotY =
scale(
static_cast<int>( slotArr[3] ) );
2904 if( slotX > 0 && slotY > 0 )
2919 drillW =
scale(
static_cast<int>( aPadstack.
m_Drill ) );
2935 bool drillIsTaller = ( drillH > drillW );
2937 if( padIsTaller != drillIsTaller )
2938 std::swap( drillW, drillH );
2941 bool isSmd = ( drillW == 0 ) || ( aPadstack.
m_LayerCount == 1 );
2951 if( drillW != drillH )
2957 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2958 pad->SetPadstack( padStack );
2959 pad->SetNumber( aPadName );
2960 pad->SetNetCode( aNetcode );
2978 if( thermalGap.has_value() )
2979 pad->SetThermalGap( thermalGap.value() );
2981 padItems.push_back( std::move(
pad ) );
2997 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2998 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
3007 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
3018 if( refDesStr.IsEmpty() )
3021 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
3028 fp->SetReference( refDesStr );
3036 fp->SetPosition( fpPos );
3037 fp->SetOrientation( rotation );
3049 const auto canonicalizeLayer = [](
BOARD_ITEM* aItem )
3052 aItem->SetLayer(
FlipLayer( aItem->GetLayer() ) );
3057 for(
const BLOCK_BASE* graphicsBlock : graphicsWalker )
3059 const uint8_t type = graphicsBlock->GetBlockType();
3065 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
3067 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
3069 canonicalizeLayer( shape.get() );
3070 fp->Add( shape.release() );
3075 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", type ),
3080 bool valueFieldSet =
false;
3084 for(
const BLOCK_BASE* textBlock : textWalker )
3086 const uint8_t type = textBlock->GetBlockType();
3098 canonicalizeLayer(
text.get() );
3100 const uint8_t textClass = strWrapper.m_Layer.m_Class;
3101 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
3114 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
3115 text->SetText( wxString(
"UNK" ) +
text->GetText() );
3123 field->
SetText( wxS(
"${REFERENCE}" ) );
3129 if( !valueFieldSet )
3135 valueFieldSet =
true;
3170 fp->Add(
text.release() );
3177 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3179 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3181 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3183 canonicalizeLayer( item.get() );
3184 fp->Add( item.release() );
3194 for(
const BLOCK_BASE* areaBlock : areaWalker )
3198 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3201 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler );
3204 canonicalizeLayer( zone.get() );
3205 fp->Add( zone.release() );
3210 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3212 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3214 canonicalizeLayer( item.get() );
3215 fp->Add( item.release() );
3223 for(
const BLOCK_BASE* padBlock : padWalker )
3245 netCode = netIt->second->GetNetCode();
3256 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3258 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3262 PAD*
pad =
static_cast<PAD*
>( item.get() );
3263 pad->SetFPRelativeOrientation( padLocalRot );
3266 item->SetFPRelativePosition( padLocalPos );
3267 fp->Add( item.release() );
3279 if( aFpInstance.
m_Layer != 0 )
3281 fp->SetOrientation( -rotation -
ANGLE_180 );
3290 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3296 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3306 const uint8_t segType = block->GetBlockType();
3319 int width =
static_cast<int>( segInfo.
m_Width );
3321 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3323 seg->SetNetCode( aNetCode );
3324 seg->SetLayer( layer );
3326 seg->SetStart(
scale( start ) );
3328 seg->SetWidth(
scale( width ) );
3330 items.push_back( std::move( seg ) );
3340 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3342 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3349 EDA_ANGLE angle = endAngle - startAngle;
3351 if( clockwise && angle <
ANGLE_0 )
3354 if( !clockwise && angle >
ANGLE_0 )
3360 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3362 arc->SetNetCode( aNetCode );
3363 arc->SetLayer( layer );
3365 arc->SetStart( start );
3368 arc->SetWidth( width );
3370 items.push_back( std::move( arc ) );
3391 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3392 via->SetPosition(
scale( viaPos ) );
3393 via->SetNetCode( aNetCode );
3418 viaDrill =
scale(
static_cast<int>( viaPadstack->
m_Drill ) );
3422 viaDrill = viaWidth / 2;
3423 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack, using fallback %d",
3429 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d) has no valid pad component, using drill-based fallback",
3431 viaWidth = viaDrill * 2;
3434 via->SetWidth(
F_Cu, viaWidth );
3435 via->SetDrill( viaDrill );
3445 std::vector<BOARD_ITEM*> newItems;
3451 const uint8_t type = block->GetBlockType();
3465 const int netCode = netIt->second->GetNetCode();
3468 for(
const BLOCK_BASE* assignBlock : assignmentWalker )
3470 if( assignBlock->GetBlockType() != 0x04 )
3480 for(
const BLOCK_BASE* connItemBlock : connWalker )
3482 const uint8_t connType = connItemBlock->GetBlockType();
3486 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3495 newItemList =
buildTrack( trackData, netCode );
3501 newItemList.push_back(
buildVia( viaData, netCode ) );
3532 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3534 newItems.push_back( newItem.get() );
3541 m_board.FinalizeBulkAdd( newItems );
3543 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3555 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3561 switch( block->GetBlockType() )
3572 newItems.push_back( std::move( rectShape ) );
3585 for(
auto& shapeItem : shapeItems )
3586 newItems.push_back( std::move( shapeItem ) );
3591 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3601 for(
const BLOCK_BASE* block : outline2Walker )
3605 switch( block->GetBlockType() )
3615 newItems.push_back( std::move( rectShape ) );
3626 newItems.push_back( std::move( rectShape ) );
3638 for(
auto& shapeItem : shapeItems )
3639 newItems.push_back( std::move( shapeItem ) );
3644 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3654 for(
const BLOCK_BASE* block : graphicContainerWalker )
3658 switch( block->GetBlockType() )
3667 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3669 for(
auto& item : graphicItems )
3670 newItems.push_back( std::move( item ) );
3675 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in graphic container walker: %#04x",
3676 block->GetBlockType() );
3684 std::vector<BOARD_ITEM*> addedItems;
3685 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3687 addedItems.push_back( item.get() );
3691 m_board.FinalizeBulkAdd( addedItems );
3702 return cacheIt->second;
3705 uint32_t currentKey = aStartKey;
3708 static constexpr int MAX_CHAIN_LENGTH = 50000;
3711 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3732 outline.
Append( shapeArc );
3736 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3743 EDA_ANGLE arcAngle = endAngle - startAngle;
3745 if( clockwise && arcAngle <
ANGLE_0 )
3748 if( !clockwise && arcAngle >
ANGLE_0 )
3755 outline.
Append( shapeArc );
3758 currentKey = arc.m_Next;
3774 currentKey = seg.m_Next;
3793 VECTOR2I topRight{ botRight.x, topLeft.
y };
3794 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3796 outline.
Append( topLeft );
3797 outline.
Append( topRight );
3798 outline.
Append( botRight );
3799 outline.
Append( botLeft );
3802 outline.
Rotate( angle, topLeft );
3814 VECTOR2I topRight{ botRight.x, topLeft.
y };
3815 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3817 outline.
Append( topLeft );
3818 outline.
Append( topRight );
3819 outline.
Append( botRight );
3820 outline.
Append( botLeft );
3823 outline.
Rotate( angle, topLeft );
3834 for(
const BLOCK_BASE* segBlock : segWalker )
3836 switch( segBlock->GetBlockType() )
3848 outline.
Append( shapeArc );
3852 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3859 EDA_ANGLE arcAngle = endAngle - startAngle;
3861 if( clockwise && arcAngle <
ANGLE_0 )
3864 if( !clockwise && arcAngle >
ANGLE_0 )
3871 outline.
Append( shapeArc );
3892 segBlock->GetBlockType() );
3918 while( holeKey != 0 )
3932 polySet.
AddHole( holeOutline );
3935 holeKey = keepout.m_Next;
3953 chain.SetClosed(
true );
3963 chain.SetClosed(
true );
3973 chain.SetClosed(
true );
3993 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
4026 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
4035 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
4040 auto zone = std::make_unique<ZONE>( &
m_board );
4045 zone->SetLayer( layer );
4058 zone->SetIsRuleArea(
true );
4059 zone->SetLayerSet( layerSet );
4060 zone->SetDoNotAllowTracks( isRouteKeepout );
4061 zone->SetDoNotAllowVias( isViaKeepout );
4062 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
4063 zone->SetDoNotAllowPads(
false );
4064 zone->SetDoNotAllowFootprints( isPackageKeepout );
4070 zone->SetZoneName(
"Route Keepin" );
4071 else if( isPackageKeepin )
4072 zone->SetZoneName(
"Package Keepin" );
4077 for(
const BLOCK_BASE* block : aRelatedBlocks )
4082 switch( block->GetBlockType() )
4086 const auto it =
m_netCache.find( block->GetKey() );
4091 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
4093 netCode = it->second->GetNetCode();
4097 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
4098 block->GetKey(), aBoundaryBlock.
GetKey() ),
4108 combinedFill.
Append( fillPolySet );
4118 zone->SetNetCode( netCode );
4124 if( isCopperZone && !combinedFill.
IsEmpty() )
4138 zone->SetIsFilled(
true );
4139 zone->SetNeedRefill(
false );
4152 std::vector<const BLOCK_BASE*> ret;
4165 if( !ptrArray || ptrArray->
m_Count == 0 )
4168 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4169 ret.resize( count );
4171 for(
size_t i = 0; i < count; i++ )
4185 if( block->GetBlockType() != 0x30 )
4188 const auto& strWrapper =
4198 if( strWrapper.GetGroupPtr() != 0 )
4206 text->GetPosition().x,
text->GetPosition().y );
4216template <std::derived_from<BOARD_ITEM> T>
4219 std::vector<BOARD_ITEM*> rawPointers;
4220 rawPointers.reserve( aItems.size() );
4222 for( std::unique_ptr<T>& item : aItems )
4224 rawPointers.push_back( item.get() );
4236 std::vector<std::unique_ptr<ZONE>> newZones;
4237 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4247 std::unique_ptr<ZONE> zone;
4250 switch( block->GetBlockType() )
4259 zone =
buildZone( *block, {}, zoneFillHandler );
4270 zone =
buildZone( *block, {}, zoneFillHandler );
4282 layerInfo = shapeData.
m_Layer;
4287 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4288 block->GetBlockType(), block->GetKey() );
4295 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4296 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4297 layerInfo.m_Subclass );
4299 newZones.push_back( std::move( zone ) );
4306 for(
const BLOCK_BASE* block : keepoutWalker )
4308 std::unique_ptr<ZONE> zone;
4310 switch( block->GetBlockType() )
4322 zone =
buildZone( *block, {}, zoneFillHandler );
4335 zone =
buildZone( *block, {}, zoneFillHandler );
4344 newZones.push_back( std::move( zone ) );
4351 int originalCount = newZones.size();
4360 int mergedCount = mergedZones.size();
4362 int keepoutCount = 0;
4363 int boundaryCount = 0;
4365 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4367 if( zone->GetIsRuleArea() )
4375 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4376 keepoutCount, originalCount - mergedCount );
4387 if( block->GetBlockType() != 0x2C )
4400 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4404 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4406 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4415 switch( keyTable->GetBlockType() )
4422 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4424 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4426 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4428 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4443 newItems.push_back( std::move( newItem ) );
4460 keyTable->GetBlockType() );
4466 if( newItems.size() > 0 )
4468 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4470 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4471 group->SetName( tableName );
4473 for(
const auto& item : newItems )
4474 group->AddItem( item.get() );
4476 newItems.push_back( std::move(
group ) );
4499 int copperShapeCount = 0;
4500 int teardropCount = 0;
4515 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4517 if( isDynCopperShape )
4519 auto zone = std::make_unique<ZONE>( &
m_board );
4522 zone->SetLayer( fill.layer );
4523 zone->SetNetCode( fill.netCode );
4524 zone->SetLocalClearance( 0 );
4530 zone->AddPolygon(
chain );
4532 zone->SetFilledPolysList( fill.layer, fractured );
4533 zone->SetIsFilled(
true );
4534 zone->SetNeedRefill(
false );
4535 zone->CalculateFilledArea();
4543 shape->SetPolyShape( fractured );
4544 shape->SetFilled(
true );
4545 shape->SetLayer( fill.layer );
4546 shape->SetNetCode( fill.netCode );
4555 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4556 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4562 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4566 if( zone->IsTeardropArea() )
4567 teardropsByNet[zone->GetNetCode()].push_back( zone );
4570 if( teardropsByNet.empty() )
4578 for(
PAD*
pad : fp->Pads() )
4580 auto it = teardropsByNet.find(
pad->GetNetCode() );
4582 if( it == teardropsByNet.end() )
4585 for(
ZONE* tdZone : it->second )
4592 pad->SetTeardropsEnabled(
true );
4606 auto it = teardropsByNet.find(
via->GetNetCode() );
4608 if( it == teardropsByNet.end() )
4611 for(
ZONE* tdZone : it->second )
4618 via->SetTeardropsEnabled(
true );
4625 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4633 static_cast<int>(
m_brdDb.m_FmtVer ),
4636 m_brdDb.m_Header->m_AllegroVersion.data() );
4709 std::vector<BOARD_ITEM*> bulkAddedItems;
4711 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4713 for(
const BLOCK_BASE* fpContainer : fpWalker )
4715 if( fpContainer->GetBlockType() == 0x2B )
4722 for(
const BLOCK_BASE* instBlock : instWalker )
4724 if( instBlock->GetBlockType() != 0x2D )
4727 wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4728 instBlock->GetBlockType(), fpBlock.
m_Key ),
4740 bulkAddedItems.push_back( fp.get() );
4746 wxString::Format(
"Failed to construct footprint for 0x2D key %#010x",
4758 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4759 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4761 if( !bulkAddedItems.empty() )
4762 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 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
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
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)
@ 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...
std::array< uint32_t, 8 > m_DrillArr
In >= V172, elements [4] and [7] hold drill dimensions: [4] = drill diameter (or width for oblong dri...
uint8_t m_Flags
Mask of PAD_FLAGS values.
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...
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:
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