31#include <unordered_set>
73#define BLK_FIELD( BLK_T, FIELD ) BlockDataAs<BLK_T>( aBlock ).FIELD
85 THROW_IO_ERRORF( wxT(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x" ),
101 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
114static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
198 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
221 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
245 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
254 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
262 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
282 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
299 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
308 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
312 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
316 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
322 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
346 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
348 if( classIt != s_ClassNames.end() )
349 className = classIt->second;
351 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
353 wxString subclassName;
356 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
358 if( classMapIt != s_SubclassNameMaps.end() )
360 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
362 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
364 if( subIt != subclassMap.end() )
365 subclassName = subIt->second;
369 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
375 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
378 return className + wxS(
"/" ) + subclassName;
421 return trace.m_Layer;
431 return shape.m_Layer;
449 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
451 return layerInfo.value();
461 if( aIndex >= aTotal - 1 )
496 if(
m_Lists.count( &aList ) == 0 )
498 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
504 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
513 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
523 classLayers.size(), aClass, aList.
m_Key );
545 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
546 const size_t numCuLayers = etchLayers.size();
548 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
550 std::vector<INPUT_LAYER_DESC> inputLayers;
552 for(
size_t li = 0; li < numCuLayers; ++li )
555 desc.
Name = etchLayers[li].m_Name;
559 inputLayers.push_back( desc );
564 int nextAutoUser = 0;
571 for(
size_t si = 0; si < layerList->size(); ++si )
573 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
582 if( layerList->at( si ).m_Name.length() > 0 )
583 desc.
Name = layerList->at( si ).m_Name;
588 inputLayers.push_back( desc );
599 desc.
Name = layerName;
603 inputLayers.push_back( desc );
613 inputLayers.push_back( desc );
619 for(
size_t li = 0; li < numCuLayers; ++li )
622 const wxString& layerName = etchLayers[li].m_Name;
624 auto it = resolvedMapping.find( layerName );
625 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
629 m_board.SetLayerName( lId, layerName );
633 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
637 auto rmIt = resolvedMapping.find( displayName );
648 auto rmIt = resolvedMapping.find( dialogName );
653 m_board.SetLayerName( rmIt->second, dialogName );
658 LSET enabledLayersMask =
m_board.GetEnabledLayers();
660 for(
const auto& [
name, layerId] : resolvedMapping )
663 enabledLayersMask |=
LSET{ layerId };
669 m_board.GetLayerName( layerId ), layerId );
673 m_board.SetEnabledLayers( enabledLayersMask );
675 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
701 && cLayerList == etchIt->second
702 && aLayerInfo.
m_Subclass < cLayerList->size() )
710 if( aLayerInfo.
m_Subclass < cLayerList->size() )
762 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
850 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
893 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
894 m_board.SetLayerName( lId, aName );
901 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
964 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
967 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
970 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1053 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1063 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1078 double result = std::round( aValue );
1080 if(
result > std::numeric_limits<int>::max() )
1081 return std::numeric_limits<int>::max();
1083 if(
result < std::numeric_limits<int>::min() )
1084 return std::numeric_limits<int>::min();
1086 return static_cast<int>(
result );
1121 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1127 const wxString& aName )
const
1129 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1130 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1131 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#zx ", aOffset );
1133 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1144 if( blk0x30 ==
nullptr )
1149 if( blk0x31 ==
nullptr )
1161 bool encountered =
false;
1165 if( blk0x36.m_Code != 0x08 )
1176 for(
const auto& item : blk0x36.m_Items )
1178 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1194 std::vector<BOARD_ITEM*> bulkAdded;
1197 m_brdDb.m_Header->m_LL_0x1B_Nets,
1204 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1209 if( netName.IsEmpty() )
1210 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1212 std::unique_ptr<NETINFO_ITEM> kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1216 bulkAdded.push_back( kiNetInfo.get() );
1220 m_board.FinalizeBulkAdd( bulkAdded );
1230 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1231 return wxEmptyString;
1234 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1237 return wxEmptyString;
1241 size_t sep = str->find(
":\\" );
1243 if( sep == std::string::npos )
1244 return wxEmptyString;
1246 std::string extracted = str->substr( sep + 2 );
1248 if( !extracted.empty() && extracted.back() ==
'\\' )
1249 extracted.pop_back();
1251 return wxString( extracted );
1260 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1269 int diffPairGap = 0;
1273 std::map<wxString, CS_DEF> constraintSets;
1276 std::map<uint32_t, wxString> keyToSetName;
1284 const wxString& resolved =
m_brdDb.GetString( csBlock.m_NameStrKey );
1286 if( !resolved.IsEmpty() )
1290 else if( csBlock.m_FieldPtr != 0 )
1296 if( setName.IsEmpty() )
1297 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1301 if( csBlock.m_DataB.empty() )
1303 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1308 const auto& record = csBlock.m_DataB[0];
1310 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1311 memcpy( fields, record.data(),
sizeof( fields ) );
1318 def.lineWidth =
scale( fields[1] );
1319 def.clearance =
scale( fields[4] );
1325 def.lineWidth =
scale( fields[0] );
1326 def.clearance =
scale( fields[1] );
1329 def.diffPairGap =
scale( fields[7] );
1331 constraintSets[setName] = def;
1332 keyToSetName[csBlock.m_NameStrKey] = setName;
1335 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1336 setName, def.lineWidth, def.clearance, def.diffPairGap );
1339 if( constraintSets.empty() )
1346 for(
const auto& [
name, def] : constraintSets )
1348 wxString ncName =
name;
1351 ncName = wxS(
"Allegro_Default" );
1353 if( netSettings->HasNetclass( ncName ) )
1356 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( ncName );
1358 if( def.lineWidth > 0 )
1359 nc->SetTrackWidth( def.lineWidth );
1361 if( def.clearance > 0 )
1362 nc->SetClearance( def.clearance );
1364 if( def.diffPairGap > 0 )
1366 nc->SetDiffPairGap( def.diffPairGap );
1369 if( def.lineWidth > 0 )
1370 nc->SetDiffPairWidth( def.lineWidth );
1373 netSettings->SetNetclass( ncName, nc );
1379 wxString defaultSetName;
1381 for(
const auto& [
name, def] : constraintSets )
1383 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1385 defaultSetName =
name;
1399 wxString assignedSetName;
1401 if( csField.has_value() )
1403 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1405 auto it = keyToSetName.find( *intVal );
1407 if( it != keyToSetName.end() )
1408 assignedSetName = it->second;
1410 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1412 if( constraintSets.count( *strVal ) )
1413 assignedSetName = *strVal;
1418 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1419 assignedSetName = defaultSetName;
1421 if( assignedSetName.IsEmpty() )
1424 wxString ncName = assignedSetName;
1427 ncName = wxS(
"Allegro_Default" );
1429 if( !netSettings->HasNetclass( ncName ) )
1432 auto netIt =
m_netCache.find( netBlk.m_Key );
1438 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1439 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1442 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1451 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1455 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1461 std::optional<int> minWidth =
1464 if( !minWidth.has_value() || minWidth.value() <= 0 )
1467 int widthNm =
scale( minWidth.value() );
1468 widthToNetKeys[widthNm].push_back( netBlk.m_Key );
1471 if( widthToNetKeys.empty() )
1477 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1479 int widthMils = ( widthNm + 12700 ) / 25400;
1480 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1482 if( netSettings->HasNetclass( ncName ) )
1485 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( ncName );
1486 nc->SetTrackWidth( widthNm );
1487 netSettings->SetNetclass( ncName, nc );
1489 for( uint32_t netKey : netKeys )
1497 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1501 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1502 ncName, widthNm, netKeys.size() );
1505 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1506 widthToNetKeys.size() );
1513 return wxEmptyString;
1518 return wxEmptyString;
1520 uint32_t tableKey = 0;
1526 tableKey = x26.m_GroupPtr;
1533 if(
next &&
next->GetBlockType() == 0x26 )
1536 tableKey = x26b.m_GroupPtr;
1547 return wxEmptyString;
1551 return wxEmptyString;
1557 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1558 return wxEmptyString;
1563 return wxEmptyString;
1567 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1576 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1579 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1582 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1590 if( groupName.empty() )
1593 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1596 if( groupToNetKeys.empty() )
1605 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1609 bool isDiffPair = ( netKeys.size() == 2 );
1610 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1611 wxString ncName = ncPrefix + groupName;
1613 if( netSettings->HasNetclass( ncName ) )
1616 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( ncName );
1620 for( uint32_t netKey : netKeys )
1627 NETCLASS* existing = it->second->GetNetClass();
1647 netSettings->SetNetclass( ncName, nc );
1649 for( uint32_t netKey : netKeys )
1657 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1667 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1668 groupName, ncName, netKeys.size() );
1672 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1673 dpCount, mgCount, groupToNetKeys.size() );
1692 std::unordered_set<LAYER_INFO> layersFound;
1694 const auto& addLayer =
1695 [&]( std::optional<LAYER_INFO>&
info )
1697 if(
info.has_value() )
1698 layersFound.insert( std::move(
info.value() ) );
1701 const auto& simpleWalker =
1713 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1714 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1715 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1725 const std::array<FILE_HEADER::LAYER_MAP_ENTRY, 25>& layerMap =
m_brdDb.m_Header->m_LayerMap;
1727 for(
size_t i = 0; i < layerMap.size(); ++i )
1729 const uint8_t classNum =
static_cast<uint8_t
>( i );
1731 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1761 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1765 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1777 m_reporter.Report( wxString::Format(
"Font def index %u requested, have %zu entries",
1805 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1806 shape->SetLayer( aLayer );
1807 shape->SetStart( start );
1808 shape->SetEnd(
end );
1811 int adjustedWidth = width;
1813 if( adjustedWidth <= 0 )
1814 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1816 shape->SetWidth( adjustedWidth );
1829 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1831 shape->SetLayer( aLayer );
1836 start.Format(),
end.Format() );
1839 start =
scale( start );
1846 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1852 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1854 shape->SetWidth( arcWidth );
1860 shape->SetCenter( c );
1861 shape->SetRadius(
radius );
1872 EDA_ANGLE angle = endangle - startangle;
1874 if( clockwise && angle <
ANGLE_0 )
1876 if( !clockwise && angle >
ANGLE_0 )
1885 shape->SetArcGeometry( start, mid,
end );
1895 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
1898 text->SetLayer( layer );
1904 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
1905 "in string wrapper (0x30) with key %#010x",
1913 if( aStrWrapper.
m_Font.has_value() )
1914 props = &aStrWrapper.
m_Font.value();
1916 if( !props && aStrWrapper.
m_Font16x.has_value() )
1921 m_reporter.Report( wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) "
1923 aStrWrapper.
m_Key ),
1943 text->SetTextAngle( textAngle );
1952 text->SetPosition( textPos + textFontOffset );
1957 text->SetMirrored(
true );
1983 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1985 const uint32_t markerShape = aPinDef.
GetShape();
1991 const auto addLine =
1992 [&](
const SEG& aSeg )
1994 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1995 shape->SetStart( aSeg.A );
1996 shape->SetEnd( aSeg.B );
1997 shapes.push_back( std::move( shape ) );
2000 const auto addPolyPts =
2001 [&](
const std::vector<VECTOR2I>& aPts )
2003 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
2004 shape->SetPolyPoints( aPts );
2005 shapes.push_back( std::move( shape ) );
2008 switch( markerShape )
2012 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
2013 shape->SetCenter(
center );
2014 shape->SetRadius( size.x / 2 );
2015 shapes.push_back( std::move( shape ) );
2021 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2022 shape->SetStart(
center - size / 2 );
2023 shape->SetEnd(
center + size / 2 );
2024 shapes.push_back( std::move( shape ) );
2029 std::unique_ptr<PCB_SHAPE> shape;
2033 for(
const SEG& seg : segs )
2041 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2042 shape->SetStart(
center - size / 2 );
2043 shape->SetEnd(
center + size / 2 );
2045 int minSize = std::min( size.x, size.y );
2046 shape->SetCornerRadius(
minSize / 2 );
2047 shapes.push_back( std::move( shape ) );
2088 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2089 markerShape, aPinDef.
m_Key );
2093 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2095 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2097 shape->SetLayer( layer );
2098 shape->SetWidth( 0 );
2100 items.push_back( std::move( shape ) );
2110 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2124 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2126 newItems.push_back( std::move( shape ) );
2133 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2135 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2136 newItems.push_back( std::move( shape ) );
2144 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2147 newItems.push_back( std::move( shape ) );
2154 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2157 newItems.push_back( std::move( shape ) );
2165 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2168 newItems.push_back( std::move( newItem ) );
2192 return static_cast<const PCB_SHAPE&
>( aItem ).GetNetCode();
2223 if( aFirst->
Type() != aSecond->
Type()
2231 return static_cast<const PCB_SHAPE*
>( aFirst )->Compare(
static_cast<const PCB_SHAPE*
>( aSecond ) ) == 0;
2234 return static_cast<const PCB_TEXT*
>( aFirst )->Compare(
static_cast<const PCB_TEXT*
>( aSecond ) ) == 0;
2245 return m_seen.insert( aItem ).second;
2273 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2287 for(
const BLOCK_BASE* segBlock : segWalker )
2289 std::unique_ptr<PCB_SHAPE> shape;
2291 switch( segBlock->GetBlockType() )
2309 segBlock->GetBlockType() );
2314 shapes.push_back( std::move( shape ) );
2323 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2326 shape->SetLayer( layer );
2333 shape->SetStart( cornerA );
2334 shape->SetEnd( cornerB );
2337 shape->Rotate( cornerA, angle );
2339 const int lineWidth = 0;
2340 shape->SetWidth( lineWidth );
2348 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2351 shape->SetLayer( layer );
2358 shape->SetStart( cornerA );
2359 shape->SetEnd( cornerB );
2362 shape->Rotate( cornerA, angle );
2364 const int lineWidth = 0;
2365 shape->SetWidth( lineWidth );
2373 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2376 shape->SetLayer( layer );
2382 if(
chain.PointCount() < 3 )
2384 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2389 chain.SetClosed(
true );
2390 shape->SetPolyShape(
chain );
2392 const int lineWidth = 0;
2393 shape->SetWidth( lineWidth );
2402 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2409 for(
const BLOCK_BASE* segBlock : segWalker )
2411 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2412 shape->SetLayer( layer );
2413 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2415 switch( segBlock->GetBlockType() )
2429 shape->SetCenter( c );
2430 shape->SetRadius(
radius );
2436 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2444 EDA_ANGLE angle = endangle - startangle;
2446 if( clockwise && angle <
ANGLE_0 )
2449 if( !clockwise && angle >
ANGLE_0 )
2455 shape->SetArcGeometry( start, mid,
end );
2468 shape->SetStart( start );
2469 shape->SetEnd(
end );
2470 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2474 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2478 shapes.push_back( std::move( shape ) );
2487 uint32_t refKey = 0x00;
2505 FOOTPRINT& aFp,
const wxString& aPadName,
2512 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2514 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
GetLayerCount() );
2517 std::optional<int> thermalGap;
2519 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2540 m_reporter.Report( wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has "
2548 m_reporter.Report( wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief",
2555 auto& layerCuProps = copperLayers[i];
2557 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2590 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2591 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.value() / (double) minDim;
2593 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2605 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2606 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.value() / (double) minDim;
2608 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2620 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2632 wxLogTrace(
traceAllegroBuilder,
"Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2649 int anchorSize =
static_cast<int>(
2650 std::min( bbox.GetWidth(), bbox.GetHeight() ) / 4 );
2652 if( anchorSize < 1 )
2655 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2657 std::shared_ptr<PCB_SHAPE> poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2659 poly->SetFilled(
true );
2660 poly->SetWidth( 0 );
2661 layerCuProps->custom_shapes.push_back( poly );
2665 wxLogTrace(
traceAllegroBuilder,
"Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2677 const int w = std::max( padComp.
m_W, 300 );
2678 const int h = std::max( padComp.
m_H, 220 );
2681 auto S = [&](
int x,
int y )
2687 outline.
Append(
S( 0, -h / 2 ) );
2688 outline.
Append(
S( w / 2, -h / 6 ) );
2689 outline.
Append(
S( w / 3, h / 2 ) );
2690 outline.
Append(
S( -w / 3, h / 2 ) );
2691 outline.
Append(
S( -w / 2, -h / 6 ) );
2695 int anchorSize =
static_cast<int>(
2698 if( anchorSize < 1 )
2701 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2703 std::shared_ptr<PCB_SHAPE> poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2705 poly->SetFilled(
true );
2706 poly->SetWidth( 0 );
2707 layerCuProps->custom_shapes.push_back( poly );
2711 m_reporter.Report( wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2713 static_cast<int>( padComp.
m_Type ),
2724 "Padstack %s: copper layer %zu antipad shape %d differs from pad shape %d",
2728 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2729 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2731 if( clearanceX && clearanceX != clearanceY )
2733 wxLogTrace(
traceAllegroBuilder,
"Padstack %s: copper layer %zu unequal antipad clearance X=%d Y=%d",
2734 padStackName, i, clearanceX, clearanceY );
2739 wxLogTrace(
traceAllegroBuilder,
"Padstack %s: copper layer %zu antipad offset %d, %d", padStackName, i,
2743 layerCuProps->clearance = clearanceX;
2752 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2761 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2762 : wxString(
"N/A" ) );
2772 if( copperLayers.size() == 0 )
2778 const auto layersEqual =
2779 [&](
size_t aFrom,
size_t aTo) ->
bool
2783 for(
size_t i = aFrom + 1; i < aTo; ++i )
2785 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2794 for(
size_t i = 0; i < copperLayers.size(); ++i )
2795 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2799 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2804 layerProps = *copperLayers.front();
2806 else if( copperLayers.front() && copperLayers.back() && layersEqual( 1, copperLayers.size() - 1 ) )
2808 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2814 if( copperLayers.size() > 2 && copperLayers[1] )
2822 for(
size_t i = 0; i < copperLayers.size(); ++i )
2824 if( !copperLayers[i] )
2828 static_cast<int>( copperLayers.size() ) );
2849 if( std::holds_alternative<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header ) )
2851 const auto& hdr16x = std::get<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header );
2853 if( hdr16x.m_SlotY > 0 )
2855 drillW =
scale(
static_cast<int>( hdr16x.m_SlotX ) );
2856 drillH =
scale(
static_cast<int>( hdr16x.m_SlotY ) );
2865 const auto& hdr17x = std::get<BLK_0x1C_PADSTACK::HEADER_v17x>( aPadstack.
m_Header );
2867 if( hdr17x.m_SlotY > 0 )
2869 drillW =
scale(
static_cast<int>( hdr17x.m_SlotX ) );
2870 drillH =
scale(
static_cast<int>( hdr17x.m_SlotY ) );
2874 drillW =
scale(
static_cast<int>( hdr17x.m_DrillSize ) );
2891 bool drillIsTaller = ( drillH > drillW );
2893 if( padIsTaller != drillIsTaller )
2894 std::swap( drillW, drillH );
2897 bool isSmd = ( drillW == 0 ) || ( aPadstack.
GetLayerCount() == 1 );
2907 if( drillW != drillH )
2913 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2914 pad->SetPadstack( padStack );
2915 pad->SetNumber( aPadName );
2916 pad->SetNetCode( aNetcode );
2934 if( thermalGap.has_value() )
2935 pad->SetThermalGap( thermalGap.value() );
2949 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
2956 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
2963 pad->SetLayerSet(
pad->GetLayerSet().reset(
F_Mask ) );
2965 pad->SetLayerSet(
pad->GetLayerSet().reset(
B_Mask ) );
2979 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2982 padItems.push_back( std::move(
pad ) );
2990 if( aUnits == wxS(
"MM" ) )
2992 else if( aUnits == wxS(
"CM" ) )
2994 else if( aUnits == wxS(
"MICRONS" ) )
2996 else if( aUnits == wxS(
"MILS" ) )
2998 else if( aUnits == wxS(
"INCH" ) )
3001 return std::nullopt;
3009 std::optional<FIELD_VALUE> fileField =
3012 const wxString* fileValue = fileField.has_value() ? std::get_if<wxString>( &fileField.value() ) :
nullptr;
3015 return std::nullopt;
3017 wxString fileName = fileValue->BeforeFirst(
',' ).Trim(
true ).Trim(
false );
3019 if( fileName.IsEmpty() )
3020 return std::nullopt;
3023 model.m_Filename = fileName;
3025 std::optional<FIELD_VALUE> placementField =
3028 const wxString* placementValue =
3029 placementField.has_value() ? std::get_if<wxString>( &placementField.value() ) :
nullptr;
3031 if( !placementValue )
3034 wxArrayString tokens = wxSplit( *placementValue,
',',
'\0' );
3036 if( tokens.size() < 7 )
3038 wxLogTrace(
traceAllegroBuilder,
" Ignoring malformed 3D placement '%s'", *placementValue );
3042 const std::optional<double> toMm =
modelUnitToMm( tokens[0].Trim(
true ).Trim(
false ).Upper() );
3044 if( !toMm.has_value() )
3050 std::array<double, 6> placement{};
3052 for(
size_t i = 0; i < placement.size(); ++i )
3054 if( !tokens[i + 1].Trim(
true ).Trim(
false ).ToCDouble( &placement[i] ) )
3056 wxLogTrace(
traceAllegroBuilder,
" Ignoring malformed 3D placement '%s'", *placementValue );
3063 model.m_Offset =
VECTOR3D( placement[0] * *toMm, placement[1] * *toMm, placement[2] * *toMm );
3064 model.m_Rotation =
VECTOR3D( -placement[3], -placement[4], -placement[5] );
3072 std::unique_ptr<FOOTPRINT> fp = std::make_unique<FOOTPRINT>( &
m_board );
3076 const bool backSide = ( aFpInstance.
m_Layer != 0 );
3085 if( refDesStr.IsEmpty() )
3088 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
3095 fp->SetReference( refDesStr );
3101 fp->SetPosition( fpPos );
3134 netCode = netIt->second->GetNetCode();
3145 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3147 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3151 PAD*
pad =
static_cast<PAD*
>( item.get() );
3152 pad->SetFPRelativeOrientation( padLocalRot );
3155 item->SetFPRelativePosition( padLocalPos );
3157 if( padDedup.
IsFirst( item.get() ) )
3158 fp->Add( item.release() );
3168 fp->Rotate( fpPos, rotation );
3173 for(
BOARD_ITEM* placed : fp->GraphicalItems() )
3185 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", aType ),
3191 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
3193 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
3195 if( fpGraphics.
IsFirst( shape.get() ) )
3196 fp->Add( shape.release() );
3200 bool valueFieldSet =
false;
3212 const uint8_t textClass = strWrapper.m_Layer.m_Class;
3213 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
3226 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
3227 text->SetText( wxString(
"UNK" ) +
text->GetText() );
3236 field->
SetText( wxS(
"${REFERENCE}" ) );
3242 if( !valueFieldSet )
3249 valueFieldSet =
true;
3284 fp->Add(
text.release() );
3291 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3293 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3295 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3297 if( fpGraphics.
IsFirst( item.get() ) )
3298 fp->Add( item.release() );
3308 for(
const BLOCK_BASE* areaBlock : areaWalker )
3312 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3315 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler, *fp );
3318 fp->Add( zone.release() );
3322 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3324 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3337 if( fpGraphics.
IsFirst( item.get() ) )
3338 fp->Add( item.release() );
3348 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3354 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3365 const uint8_t segType = block->GetBlockType();
3377 int width =
static_cast<int>( segInfo.
m_Width );
3379 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3381 seg->SetNetCode( aNetCode );
3382 seg->SetLayer( layer );
3384 seg->SetStart(
scale( start ) );
3386 seg->SetWidth(
scale( width ) );
3388 items.push_back( std::move( seg ) );
3398 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3400 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3407 EDA_ANGLE angle = endAngle - startAngle;
3409 if( clockwise && angle <
ANGLE_0 )
3412 if( !clockwise && angle >
ANGLE_0 )
3418 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3420 arc->SetNetCode( aNetCode );
3421 arc->SetLayer( layer );
3423 arc->SetStart( start );
3426 arc->SetWidth( width );
3428 items.push_back( std::move( arc ) );
3449 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3450 via->SetPosition(
scale( viaPos ) );
3451 via->SetNetCode( aNetCode );
3465 const int totalCu =
m_board.GetCopperLayerCount();
3469 int endLayer = startLayer + layerCount - 1;
3471 if( layerCount > 1 && layerCount < totalCu )
3475 const bool touchesOuter = ( startLayer == 0 ) || ( endLayer == totalCu - 1 );
3491 viaDrill = viaWidth / 2;
3492 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3493 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack '%s' key %#010x, using fallback %d",
3499 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3500 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d) in padstack '%s' key %#010x has no valid pad component, "
3501 "using drill-based fallback (%d * 2)",
3503 viaWidth = viaDrill * 2;
3506 via->SetWidth(
F_Cu, viaWidth );
3507 via->SetDrill( viaDrill );
3517 std::vector<BOARD_ITEM*> newItems;
3522 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3534 const int netCode = netIt->second->GetNetCode();
3539 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3549 for(
const BLOCK_BASE* connItemBlock : connWalker )
3551 const uint8_t connType = connItemBlock->GetBlockType();
3555 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3563 newItemList =
buildTrack( trackData, netCode );
3569 newItemList.push_back(
buildVia( viaData, netCode ) );
3593 wxLogTrace(
traceAllegroBuilder,
" Unhandled connected item code: %#04x", (
int) connType );
3598 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3600 stampIds( *newItem, connItemBlock->GetKey(), idSeq );
3601 newItems.push_back( newItem.get() );
3608 m_board.FinalizeBulkAdd( newItems );
3610 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3622 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3628 switch( block->GetBlockType() )
3640 newItems.push_back( std::move( rectShape ) );
3654 for( std::unique_ptr<PCB_SHAPE>& shapeItem : shapeItems )
3657 newItems.push_back( std::move( shapeItem ) );
3663 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3673 for(
const BLOCK_BASE* block : outline2Walker )
3677 switch( block->GetBlockType() )
3688 newItems.push_back( std::move( rectShape ) );
3700 newItems.push_back( std::move( rectShape ) );
3713 for( std::unique_ptr<PCB_SHAPE>& shapeItem : shapeItems )
3716 newItems.push_back( std::move( shapeItem ) );
3721 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3739 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3742 for( std::unique_ptr<PCB_SHAPE>& item : graphicItems )
3744 stampIds( *item, graphicContainer.m_Key, idSeq );
3745 newItems.push_back( std::move( item ) );
3751 std::vector<BOARD_ITEM*> addedItems;
3754 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3762 addedItems.push_back( item.get() );
3766 m_board.FinalizeBulkAdd( addedItems );
3784 return cacheIt->second;
3789 uint32_t currentKey = aStartKey;
3792 static constexpr int MAX_CHAIN_LENGTH = 50000;
3795 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3816 start = aXform.
Apply( start );
3819 outline.
Append( shapeArc );
3823 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3830 EDA_ANGLE arcAngle = endAngle - startAngle;
3832 if( clockwise && arcAngle <
ANGLE_0 )
3835 if( !clockwise && arcAngle >
ANGLE_0 )
3841 start = aXform.
Apply( start );
3842 mid = aXform.
Apply( mid );
3846 outline.
Append( shapeArc );
3849 currentKey = arc.m_Next;
3864 currentKey = seg.m_Next;
3883 VECTOR2I topRight{ botRight.x, topLeft.
y };
3884 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3886 outline.
Append( topLeft );
3887 outline.
Append( topRight );
3888 outline.
Append( botRight );
3889 outline.
Append( botLeft );
3892 outline.
Rotate( angle, topLeft );
3894 for(
int i = 0; i < outline.
PointCount(); i++ )
3907 VECTOR2I topRight{ botRight.x, topLeft.
y };
3908 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3910 outline.
Append( topLeft );
3911 outline.
Append( topRight );
3912 outline.
Append( botRight );
3913 outline.
Append( botLeft );
3916 outline.
Rotate( angle, topLeft );
3918 for(
int i = 0; i < outline.
PointCount(); i++ )
3948 while( holeKey != 0 )
3962 polySet.
AddHole( holeOutline );
3965 holeKey = keepout.m_Next;
3984 chain.SetClosed(
true );
3994 chain.SetClosed(
true );
4004 chain.SetClosed(
true );
4024 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
4057 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
4067 xform = fp->GetTransform().
Invert();
4073 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
4078 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( &aParent );
4083 zone->SetLayer( layer );
4096 zone->SetIsRuleArea(
true );
4097 zone->SetLayerSet( layerSet );
4098 zone->SetDoNotAllowTracks( isRouteKeepout );
4099 zone->SetDoNotAllowVias( isViaKeepout );
4100 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
4101 zone->SetDoNotAllowPads(
false );
4102 zone->SetDoNotAllowFootprints( isPackageKeepout );
4108 zone->SetZoneName(
"Route Keepin" );
4109 else if( isPackageKeepin )
4110 zone->SetZoneName(
"Package Keepin" );
4115 for(
const BLOCK_BASE* block : aRelatedBlocks )
4120 switch( block->GetBlockType() )
4124 const auto it =
m_netCache.find( block->GetKey() );
4129 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
4131 netCode = it->second->GetNetCode();
4135 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
4136 block->GetKey(), aBoundaryBlock.
GetKey() ),
4146 combinedFill.
Append( fillPolySet );
4156 zone->SetNetCode( netCode );
4159 zone->AddPolygon(
chain );
4162 if( isCopperZone && !combinedFill.
IsEmpty() )
4176 zone->SetIsFilled(
true );
4177 zone->SetNeedRefill(
false );
4190 std::vector<const BLOCK_BASE*> ret;
4203 if( !ptrArray || ptrArray->
m_Count == 0 )
4206 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4207 ret.resize( count );
4209 for(
size_t i = 0; i < count; i++ )
4230 if( strWrapper.GetGroupPtr() != 0 )
4251template <std::derived_from<BOARD_ITEM> T>
4254 std::vector<BOARD_ITEM*> rawPointers;
4255 rawPointers.reserve( aItems.size() );
4257 for( std::unique_ptr<T>& item : aItems )
4259 rawPointers.push_back( item.get() );
4271 std::vector<std::unique_ptr<ZONE>> newZones;
4272 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4282 std::unique_ptr<ZONE> zone;
4285 switch( block->GetBlockType() )
4317 layerInfo = shapeData.
m_Layer;
4322 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4323 block->GetBlockType(), block->GetKey() );
4330 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4331 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4332 layerInfo.m_Subclass );
4334 stampIds( *zone, block->GetKey() );
4335 newZones.push_back( std::move( zone ) );
4342 for(
const BLOCK_BASE* block : keepoutWalker )
4344 std::unique_ptr<ZONE> zone;
4346 switch( block->GetBlockType() )
4380 stampIds( *zone, block->GetKey() );
4381 newZones.push_back( std::move( zone ) );
4388 int originalCount = newZones.size();
4397 int mergedCount = mergedZones.size();
4399 int keepoutCount = 0;
4400 int boundaryCount = 0;
4402 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4404 if( zone->GetIsRuleArea() )
4412 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4413 keepoutCount, originalCount - mergedCount );
4430 const wxString& tableName =
m_brdDb.GetString( tableData.m_StringPtr );
4432 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4436 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4438 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4439 tableData.m_Key, tableData.m_Ptr1 );
4443 wxLogTrace(
traceAllegroBuilder,
" Key table pointer %#010x is invalid", tableData.m_Ptr1 );
4447 switch( keyTable->GetBlockType() )
4453 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4455 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4457 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4459 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4475 newItems.push_back( std::move( newItem ) );
4492 keyTable->GetBlockType() );
4498 if( newItems.size() > 0 )
4500 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4502 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4503 group->SetName( tableName );
4507 for(
const std::unique_ptr<BOARD_ITEM>& item : newItems )
4509 stampIds( *item, tableData.m_Key, idSeq );
4510 group->AddItem( item.get() );
4514 newItems.push_back( std::move(
group ) );
4537 int copperShapeCount = 0;
4538 int teardropCount = 0;
4555 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4557 if( isDynCopperShape )
4559 std::unique_ptr<ZONE> zone = std::make_unique<ZONE>( &
m_board );
4562 zone->SetLayer( fill.layer );
4563 zone->SetNetCode( fill.netCode );
4564 zone->SetLocalClearance( 0 );
4570 zone->AddPolygon(
chain );
4572 zone->SetFilledPolysList( fill.layer, fractured );
4573 zone->SetIsFilled(
true );
4574 zone->SetNeedRefill(
false );
4575 zone->CalculateFilledArea();
4584 shape->SetPolyShape( fractured );
4585 shape->SetFilled(
true );
4586 shape->SetLayer( fill.layer );
4587 shape->SetNetCode( fill.netCode );
4593 stampIds( *shape, fillKey, idSeq );
4600 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4601 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4607 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4611 if( zone->IsTeardropArea() )
4612 teardropsByNet[zone->GetNetCode()].push_back( zone );
4615 if( teardropsByNet.empty() )
4623 for(
PAD*
pad : fp->Pads() )
4625 auto it = teardropsByNet.find(
pad->GetNetCode() );
4627 if( it == teardropsByNet.end() )
4630 for(
ZONE* tdZone : it->second )
4637 pad->SetTeardropsEnabled(
true );
4651 auto it = teardropsByNet.find(
via->GetNetCode() );
4653 if( it == teardropsByNet.end() )
4656 for(
ZONE* tdZone : it->second )
4663 via->SetTeardropsEnabled(
true );
4670 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4752 std::vector<BOARD_ITEM*> bulkAddedItems;
4754 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4761 [
this, &fpBlock]( uint8_t aType,
const BLOCK_BASE& )
4763 m_reporter.Report( wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4777 if( model3D.has_value() )
4778 fp->Models().push_back( *model3D );
4781 bulkAddedItems.push_back( fp.get() );
4786 m_reporter.Report( wxString::Format(
"Failed to construct footprint for 0x2D key %#010x", inst.m_Key ),
4795 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4796 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4798 if( !bulkAddedItems.empty() )
4799 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 std::optional< LAYER_INFO > tryLayerFromBlock(const BLOCK_BASE &aBlock)
Some blocks report layer info - if they do, return it else std::nullopt.
static PCB_LAYER_ID nthCopperLayerId(int aIndex, int aTotal)
Map a 0-based copper index (0 = F_Cu, aTotal-1 = B_Cu) to a KiCad copper layer.
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)
#define BLK_FIELD(BLK_T, FIELD)
static std::optional< FP_3DMODEL > build3DModel(const BRD_DB &aDb, const BLK_0x2B_FOOTPRINT_DEF &aFpDef)
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 graphicNetCode(const BOARD_ITEM &aItem)
static int clampForScale(double aValue)
static std::optional< double > modelUnitToMm(const wxString &aUnits)
Utility functions that operate over BRD_DBs and BLOCKs.
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
This is the actual type code as read from the file.
Rejects graphics that repeat one already accepted into the same container.
bool IsFirst(const BOARD_ITEM *aItem)
True when this graphic has not been seen before, and records it.
std::unordered_set< const BOARD_ITEM *, GRAPHIC_KEY_HASH, GRAPHIC_KEY_EQ > m_seen
VECTOR2I scale(const VECTOR2I &aVector) 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.
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.
SHAPE_POLY_SET tryBuildZoneShape(const BLOCK_BASE &aBlock, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
Try to build a zone shape for the given block, with holes.
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.
static void stampIds(BOARD_ITEM &aItem, uint32_t aKey, uint32_t &aSeq)
Give aItem and its children ids derived from the Allegro block they came from.
GRAPHIC_DEDUP m_boardGraphics
Coincidence filter for everything added straight to the board, which is one container.
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
const T * expectBlockByKey(uint32_t aKey) const
Get a block by its key, and check that it is of the expected type.
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.
SHAPE_POLY_SET shapeToPolySet(const BLK_0x28_SHAPE &aShape, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
std::unique_ptr< PCB_SHAPE > buildArc(const BLK_0x01_ARC &aArc, const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aLayer, BOARD_ITEM_CONTAINER &aParent)
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
void applyConstraintSets()
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
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
SHAPE_LINE_CHAIN buildOutline(const BLK_0x0E_RECT &aRect, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
SHAPE_LINE_CHAIN buildSegmentChain(uint32_t aStartKey, const TRANSFORM_TRS &aXform=TRANSFORM_TRS()) const
Walk a geometry chain (0x01 arcs and 0x15-17 segments) starting from the given key,...
std::unique_ptr< ZONE > buildZone(const BLOCK_BASE &aBoundaryBlock, const std::vector< const BLOCK_BASE * > &aRelatedBlocks, ZONE_FILL_HANDLER &aZoneFillHandler, BOARD_ITEM_CONTAINER &aParent)
Build a ZONE from an 0x0E, 0x24 or 0x28 block.
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 board database representing the contents of a .brd (and presumably .dra) file.
std::unique_ptr< FILE_HEADER > m_Header
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
Range-for-compatible walker over a linked list of BLOCK_BASE objects in a BRD_DB.
Range-for-compatible walker that yields only typed data from a linked list.
void SetMismatchReporter(MISMATCH_REPORTER aReporter)
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...
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction, RECURSE_MODE aMode) const
Invoke a function on all children.
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
KICAD_T Type() const
Returns the type of object.
virtual void SetFilled(bool aFlag)
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
static KIID FromName(const std::string &aName)
Return a KIID derived from a name, the same name always gives the same KIID.
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
int GetWidth() const override
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void SetTextAngle(const EDA_ANGLE &aAngle) override
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 SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
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 & CPoint(int aIndex) const
Return a reference to a given point in 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)
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.
SHAPE_POLY_SET GetBoardOutline() const
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
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
int GetPenSizeForNormal(int aTextSize)
static const wxChar *const traceAllegroBuilder
Flag to enable debug output of Allegro board construction.
static constexpr void hash_combine(std::size_t &seed)
This is a dummy function to take the final case of hash_combine below.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
#define MAX_USER_DEFINED_LAYERS
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
@ LEFT_RIGHT
Flip left to right (around the Y axis)
@ THROW
THROW_IO_ERROR on mismatch.
@ LOG_TRACE
wxLogTrace the mismatch and skip
@ REPORT
invoke a user-supplied callback, then skip
std::optional< FIELD_VALUE > GetFirstFieldOfType(const BRD_DB &aDb, uint32_t aFieldsPtr, uint32_t aEndKey, uint16_t aFieldCode)
Look up the first 0x03 FIELD value of a given type in a linked field chain.
std::optional< int > GetFirstFieldOfTypeInt(const BRD_DB &aDb, uint32_t aFieldsPtr, uint32_t aEndKey, uint16_t aFieldCode)
Convenience wrapper around GetFirstFieldOfType() for integer-valued fields.
@ MODEL_3D_PLACEMENT
3D model units, XYZ offset and XYZ rotation
@ MODEL_3D_FILE
3D model file name, size, mtime and display colour
@ PHYS_CONSTRAINT_SET
Physical Constraint Set assignment.
const BLK_T & BlockDataAs(const BLOCK_BASE &aBlock)
Cast a BLOCK_BASE to a typed BLOCK<T> and return the data.
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:
static constexpr uint8_t BLOCK_TYPE_CODE
uint32_t m_MatchGroupPtr
Diff pair / match group pointer (0x26 or 0x2C)
Padstack definition containing drill dimensions and a table of per-layer pad/antipad/thermal componen...
size_t m_NumCompsPerLayer
uint32_t GetDrillSize() const
size_t m_NumFixedCompEntries
How many of the entries are fixed roles (after this is n*layers)
std::vector< PADSTACK_COMPONENT > m_Components
Collection of components that make up the padstack.
uint32_t GetLayerCount() const
Physical constraint sets containing trace width, clearance, and routing rules.
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.
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),...
Fixed-capacity pointer array (100 entries).
std::array< uint32_t, 100 > m_Ptrs
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
size_t operator()(const BOARD_ITEM *aItem) const
@ 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.
Substruct in a padstack object.
@ TYPE_CHAMFERED_RECTANGLE
COND_GE< FMT_VER::V_172, int32_t > m_Z1
uint32_t m_ShapePtr
Seems to point to various things:
This is all the info needed to do the fill of one layer of one zone.
SHAPE_POLY_SET m_CombinedFill
The wider filled area we will chop a piece out of for this layer of this zone.
The features of a padstack that can vary between copper layers All parameters are optional; leaving t...
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
size_t operator()(const LAYER_INFO &aLayerInfo) const noexcept
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
VECTOR3< double > VECTOR3D
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