29#include <unordered_set>
69#define BLK_FIELD( BLK_T, FIELD ) BlockDataAs<BLK_T>( aBlock ).FIELD
82 wxString::Format(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x",
96 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
109static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
193 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
216 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
240 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
249 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
257 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
277 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
294 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
303 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
307 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
311 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
317 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
341 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
343 if( classIt != s_ClassNames.end() )
344 className = classIt->second;
346 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
348 wxString subclassName;
351 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
353 if( classMapIt != s_SubclassNameMaps.end() )
355 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
357 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
359 if( subIt != subclassMap.end() )
360 subclassName = subIt->second;
364 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
370 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
373 return className + wxS(
"/" ) + subclassName;
416 return trace.m_Layer;
426 return shape.m_Layer;
444 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
446 return layerInfo.value();
456 if( aIndex >= aTotal - 1 )
467 return (
static_cast<int64_t
>(
static_cast<uint32_t
>( aX ) ) << 32 )
468 |
static_cast<uint32_t
>( aY );
500 if(
m_Lists.count( &aList ) == 0 )
502 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
508 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
517 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
527 classLayers.size(), aClass, aList.
m_Key );
549 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
550 const size_t numCuLayers = etchLayers.size();
552 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
554 std::vector<INPUT_LAYER_DESC> inputLayers;
556 for(
size_t li = 0; li < numCuLayers; ++li )
559 desc.
Name = etchLayers[li].m_Name;
563 inputLayers.push_back( desc );
568 int nextAutoUser = 0;
575 for(
size_t si = 0; si < layerList->size(); ++si )
577 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
586 if( layerList->at( si ).m_Name.length() > 0 )
587 desc.
Name = layerList->at( si ).m_Name;
592 inputLayers.push_back( desc );
603 desc.
Name = layerName;
607 inputLayers.push_back( desc );
617 inputLayers.push_back( desc );
623 for(
size_t li = 0; li < numCuLayers; ++li )
626 const wxString& layerName = etchLayers[li].m_Name;
628 auto it = resolvedMapping.find( layerName );
629 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
633 m_board.SetLayerName( lId, layerName );
637 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
641 auto rmIt = resolvedMapping.find( displayName );
652 auto rmIt = resolvedMapping.find( dialogName );
657 m_board.SetLayerName( rmIt->second, dialogName );
662 LSET enabledLayersMask =
m_board.GetEnabledLayers();
664 for(
const auto& [
name, layerId] : resolvedMapping )
667 enabledLayersMask |=
LSET{ layerId };
673 m_board.GetLayerName( layerId ), layerId );
677 m_board.SetEnabledLayers( enabledLayersMask );
679 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
704 && cLayerList == etchIt->second
705 && aLayerInfo.
m_Subclass < cLayerList->size() )
713 if( aLayerInfo.
m_Subclass < cLayerList->size() )
765 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
853 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
896 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
897 m_board.SetLayerName( lId, aName );
904 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
967 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
970 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
973 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1056 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1066 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1081 double result = std::round( aValue );
1083 if(
result > std::numeric_limits<int>::max() )
1084 return std::numeric_limits<int>::max();
1086 if(
result < std::numeric_limits<int>::min() )
1087 return std::numeric_limits<int>::min();
1089 return static_cast<int>(
result );
1124 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1130 const wxString& aName )
const
1132 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1133 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1134 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#zx ", aOffset );
1136 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1147 if( blk0x30 ==
nullptr )
1152 if( blk0x31 ==
nullptr )
1164 bool encountered =
false;
1168 if( blk0x36.m_Code != 0x08 )
1179 for(
const auto& item : blk0x36.m_Items )
1181 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1197 std::vector<BOARD_ITEM*> bulkAdded;
1200 m_brdDb.m_Header->m_LL_0x1B_Nets,
1207 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1212 if( netName.IsEmpty() )
1213 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1215 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1219 bulkAdded.push_back( kiNetInfo.get() );
1223 m_board.FinalizeBulkAdd( bulkAdded );
1233 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1234 return wxEmptyString;
1237 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1240 return wxEmptyString;
1244 size_t sep = str->find(
":\\" );
1246 if( sep == std::string::npos )
1247 return wxEmptyString;
1249 std::string extracted = str->substr( sep + 2 );
1251 if( !extracted.empty() && extracted.back() ==
'\\' )
1252 extracted.pop_back();
1254 return wxString( extracted );
1263 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1272 int diffPairGap = 0;
1276 std::map<wxString, CS_DEF> constraintSets;
1279 std::map<uint32_t, wxString> keyToSetName;
1287 const wxString& resolved =
m_brdDb.GetString( csBlock.m_NameStrKey );
1289 if( !resolved.IsEmpty() )
1293 else if( csBlock.m_FieldPtr != 0 )
1299 if( setName.IsEmpty() )
1300 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1304 if( csBlock.m_DataB.empty() )
1306 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1311 const auto& record = csBlock.m_DataB[0];
1313 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1314 memcpy( fields, record.data(),
sizeof( fields ) );
1321 def.lineWidth =
scale( fields[1] );
1322 def.clearance =
scale( fields[4] );
1328 def.lineWidth =
scale( fields[0] );
1329 def.clearance =
scale( fields[1] );
1332 def.diffPairGap =
scale( fields[7] );
1334 constraintSets[setName] = def;
1335 keyToSetName[csBlock.m_NameStrKey] = setName;
1338 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1339 setName, def.lineWidth, def.clearance, def.diffPairGap );
1342 if( constraintSets.empty() )
1349 for(
const auto& [
name, def] : constraintSets )
1351 wxString ncName =
name;
1354 ncName = wxS(
"Allegro_Default" );
1356 if( netSettings->HasNetclass( ncName ) )
1359 auto nc = std::make_shared<NETCLASS>( ncName );
1361 if( def.lineWidth > 0 )
1362 nc->SetTrackWidth( def.lineWidth );
1364 if( def.clearance > 0 )
1365 nc->SetClearance( def.clearance );
1367 if( def.diffPairGap > 0 )
1369 nc->SetDiffPairGap( def.diffPairGap );
1372 if( def.lineWidth > 0 )
1373 nc->SetDiffPairWidth( def.lineWidth );
1376 netSettings->SetNetclass( ncName, nc );
1382 wxString defaultSetName;
1384 for(
const auto& [
name, def] : constraintSets )
1386 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1388 defaultSetName =
name;
1402 wxString assignedSetName;
1404 if( csField.has_value() )
1406 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1408 auto it = keyToSetName.find( *intVal );
1410 if( it != keyToSetName.end() )
1411 assignedSetName = it->second;
1413 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1415 if( constraintSets.count( *strVal ) )
1416 assignedSetName = *strVal;
1421 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1422 assignedSetName = defaultSetName;
1424 if( assignedSetName.IsEmpty() )
1427 wxString ncName = assignedSetName;
1430 ncName = wxS(
"Allegro_Default" );
1432 if( !netSettings->HasNetclass( ncName ) )
1435 auto netIt =
m_netCache.find( netBlk.m_Key );
1441 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1442 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1445 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1454 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1458 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1464 std::optional<int> minWidth =
1467 if( !minWidth.has_value() || minWidth.value() <= 0 )
1470 int widthNm =
scale( minWidth.value() );
1471 widthToNetKeys[widthNm].push_back( netBlk.m_Key );
1474 if( widthToNetKeys.empty() )
1480 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1482 int widthMils = ( widthNm + 12700 ) / 25400;
1483 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1485 if( netSettings->HasNetclass( ncName ) )
1488 auto nc = std::make_shared<NETCLASS>( ncName );
1489 nc->SetTrackWidth( widthNm );
1490 netSettings->SetNetclass( ncName, nc );
1492 for( uint32_t netKey : netKeys )
1500 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1504 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1505 ncName, widthNm, netKeys.size() );
1508 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1509 widthToNetKeys.size() );
1516 return wxEmptyString;
1521 return wxEmptyString;
1523 uint32_t tableKey = 0;
1529 tableKey = x26.m_GroupPtr;
1536 if(
next &&
next->GetBlockType() == 0x26 )
1539 tableKey = x26b.m_GroupPtr;
1550 return wxEmptyString;
1554 return wxEmptyString;
1560 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1561 return wxEmptyString;
1566 return wxEmptyString;
1570 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1579 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1582 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1585 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1593 if( groupName.empty() )
1596 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1599 if( groupToNetKeys.empty() )
1608 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1612 bool isDiffPair = ( netKeys.size() == 2 );
1613 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1614 wxString ncName = ncPrefix + groupName;
1616 if( netSettings->HasNetclass( ncName ) )
1619 auto nc = std::make_shared<NETCLASS>( ncName );
1623 for( uint32_t netKey : netKeys )
1630 NETCLASS* existing = it->second->GetNetClass();
1650 netSettings->SetNetclass( ncName, nc );
1652 for( uint32_t netKey : netKeys )
1660 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1670 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1671 groupName, ncName, netKeys.size() );
1675 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1676 dpCount, mgCount, groupToNetKeys.size() );
1695 std::unordered_set<LAYER_INFO> layersFound;
1697 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1699 if(
info.has_value() )
1701 layersFound.insert( std::move(
info.value() ) );
1715 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1716 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1717 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1727 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1729 for(
size_t i = 0; i < layerMap.size(); ++i )
1731 const uint8_t classNum =
static_cast<uint8_t
>( i );
1733 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1762 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1766 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1779 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
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() )
1922 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
1923 aStrWrapper.
m_Key ),
1939 text->SetTextAngle( textAngle );
1948 text->SetPosition( textPos + textFontOffset );
1951 text->SetMirrored(
true );
1976 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1978 const uint32_t markerShape = aPinDef.
GetShape();
1984 const auto addLine = [&](
const SEG& aSeg )
1986 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1987 shape->SetStart( aSeg.A );
1988 shape->SetEnd( aSeg.B );
1989 shapes.push_back( std::move( shape ) );
1992 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
1994 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
1995 shape->SetPolyPoints( aPts );
1996 shapes.push_back( std::move( shape ) );
1999 switch( markerShape )
2003 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
2004 shape->SetCenter(
center );
2005 shape->SetRadius( size.x / 2 );
2006 shapes.push_back( std::move( shape ) );
2012 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2013 shape->SetStart(
center - size / 2 );
2014 shape->SetEnd(
center + size / 2 );
2015 shapes.push_back( std::move( shape ) );
2020 std::unique_ptr<PCB_SHAPE> shape;
2024 for(
const SEG& seg : segs )
2033 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2034 shape->SetStart(
center - size / 2 );
2035 shape->SetEnd(
center + size / 2 );
2037 int minSize = std::min( size.x, size.y );
2038 shape->SetCornerRadius(
minSize / 2 );
2039 shapes.push_back( std::move( shape ) );
2081 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2082 markerShape, aPinDef.
m_Key );
2087 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2088 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2090 shape->SetLayer( layer );
2091 shape->SetWidth( 0 );
2093 items.push_back( std::move( shape ) );
2103 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2117 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2119 newItems.push_back( std::move( shape ) );
2126 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2127 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2128 newItems.push_back( std::move( shape ) );
2135 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2137 newItems.push_back( std::move( shape ) );
2143 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2145 newItems.push_back( std::move( shape ) );
2152 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2154 newItems.push_back( std::move( newItem ) );
2177 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2191 for(
const BLOCK_BASE* segBlock : segWalker )
2193 std::unique_ptr<PCB_SHAPE> shape;
2195 switch( segBlock->GetBlockType() )
2214 segBlock->GetBlockType() );
2220 shapes.push_back( std::move( shape ) );
2229 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2232 shape->SetLayer( layer );
2239 shape->SetStart( cornerA );
2240 shape->SetEnd( cornerB );
2243 shape->Rotate( cornerA, angle );
2245 const int lineWidth = 0;
2246 shape->SetWidth( lineWidth );
2254 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2257 shape->SetLayer( layer );
2264 shape->SetStart( cornerA );
2265 shape->SetEnd( cornerB );
2268 shape->Rotate( cornerA, angle );
2270 const int lineWidth = 0;
2271 shape->SetWidth( lineWidth );
2279 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2282 shape->SetLayer( layer );
2288 if(
chain.PointCount() < 3 )
2290 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2295 chain.SetClosed(
true );
2296 shape->SetPolyShape(
chain );
2298 const int lineWidth = 0;
2299 shape->SetWidth( lineWidth );
2308 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2315 for(
const BLOCK_BASE* segBlock : segWalker )
2317 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2318 shape->SetLayer( layer );
2319 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2321 switch( segBlock->GetBlockType() )
2335 shape->SetCenter( c );
2336 shape->SetRadius(
radius );
2342 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2350 EDA_ANGLE angle = endangle - startangle;
2352 if( clockwise && angle <
ANGLE_0 )
2355 if( !clockwise && angle >
ANGLE_0 )
2361 shape->SetArcGeometry( start, mid,
end );
2374 shape->SetStart( start );
2375 shape->SetEnd(
end );
2376 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2380 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2384 shapes.push_back( std::move( shape ) );
2393 uint32_t refKey = 0x00;
2411 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2417 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2419 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
GetLayerCount() );
2422 std::optional<int> thermalGap;
2424 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2443 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2450 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2456 auto& layerCuProps = copperLayers[i];
2458 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2491 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2492 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.value() / (double) minDim;
2494 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2506 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2507 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.value() / (double) minDim;
2509 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2521 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2534 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2535 padStackName, i, padComp.
m_StrPtr );
2550 int anchorSize =
static_cast<int>(
2553 if( anchorSize < 1 )
2556 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2558 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2560 poly->SetFilled(
true );
2561 poly->SetWidth( 0 );
2562 layerCuProps->custom_shapes.push_back( poly );
2567 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2579 const int w = std::max( padComp.
m_W, 300 );
2580 const int h = std::max( padComp.
m_H, 220 );
2583 auto S = [&](
int x,
int y )
2589 outline.
Append(
S( 0, -h / 2 ) );
2590 outline.
Append(
S( w / 2, -h / 6 ) );
2591 outline.
Append(
S( w / 3, h / 2 ) );
2592 outline.
Append(
S( -w / 3, h / 2 ) );
2593 outline.
Append(
S( -w / 2, -h / 6 ) );
2597 int anchorSize =
static_cast<int>(
2600 if( anchorSize < 1 )
2603 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2605 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2607 poly->SetFilled(
true );
2608 poly->SetWidth( 0 );
2609 layerCuProps->custom_shapes.push_back( poly );
2614 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2615 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2625 "differs from pad shape %d",
2629 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2630 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2632 if( clearanceX && clearanceX != clearanceY )
2635 "clearance X=%d Y=%d",
2636 padStackName, i, clearanceX, clearanceY );
2639 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2643 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2646 layerCuProps->clearance = clearanceX;
2655 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2662 "Padstack %s: thermal relief type=%d, gap=%snm",
2663 padStackName, thermalComp.
m_Type,
2664 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2665 : wxString(
"N/A" ) );
2675 if( copperLayers.size() == 0 )
2681 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2684 for(
size_t i = aFrom + 1; i < aTo; ++i )
2686 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2695 for(
size_t i = 0; i < copperLayers.size(); ++i )
2697 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2702 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2707 layerProps = *copperLayers.front();
2709 else if( copperLayers.front() && copperLayers.back()
2710 && layersEqual( 1, copperLayers.size() - 1 ) )
2712 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2718 if( copperLayers.size() > 2 && copperLayers[1] )
2726 for(
size_t i = 0; i < copperLayers.size(); ++i )
2728 if( !copperLayers[i] )
2732 static_cast<int>( copperLayers.size() ) );
2753 if( std::holds_alternative<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header ) )
2755 const auto& hdr16x = std::get<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header );
2757 if( hdr16x.m_SlotY > 0 )
2759 drillW =
scale(
static_cast<int>( hdr16x.m_SlotX ) );
2760 drillH =
scale(
static_cast<int>( hdr16x.m_SlotY ) );
2769 const auto& hdr17x = std::get<BLK_0x1C_PADSTACK::HEADER_v17x>( aPadstack.
m_Header );
2771 if( hdr17x.m_SlotY > 0 )
2773 drillW =
scale(
static_cast<int>( hdr17x.m_SlotX ) );
2774 drillH =
scale(
static_cast<int>( hdr17x.m_SlotY ) );
2778 drillW =
scale(
static_cast<int>( hdr17x.m_DrillSize ) );
2795 bool drillIsTaller = ( drillH > drillW );
2797 if( padIsTaller != drillIsTaller )
2798 std::swap( drillW, drillH );
2801 bool isSmd = ( drillW == 0 ) || ( aPadstack.
GetLayerCount() == 1 );
2811 if( drillW != drillH )
2817 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2818 pad->SetPadstack( padStack );
2819 pad->SetNumber( aPadName );
2820 pad->SetNetCode( aNetcode );
2838 if( thermalGap.has_value() )
2839 pad->SetThermalGap( thermalGap.value() );
2841 padItems.push_back( std::move(
pad ) );
2857 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2858 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2867 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
2871 const bool backSide = ( aFpInstance.
m_Layer != 0 );
2880 if( refDesStr.IsEmpty() )
2883 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
2890 fp->SetReference( refDesStr );
2903 fp->SetPosition( fpPos );
2904 fp->SetOrientation( rotation );
2919 const auto canonicalizeLayer = [backSide, fpPos](
BOARD_ITEM* aItem )
2930 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", aType ),
2936 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
2938 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2940 canonicalizeLayer( shape.get() );
2941 fp->Add( shape.release() );
2945 bool valueFieldSet =
false;
2957 canonicalizeLayer(
text.get() );
2959 const uint8_t textClass = strWrapper.m_Layer.m_Class;
2960 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
2973 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
2974 text->SetText( wxString(
"UNK" ) +
text->GetText() );
2982 field->
SetText( wxS(
"${REFERENCE}" ) );
2988 if( !valueFieldSet )
2994 valueFieldSet =
true;
3029 fp->Add(
text.release() );
3036 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3038 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3040 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3042 canonicalizeLayer( item.get() );
3043 fp->Add( item.release() );
3053 for(
const BLOCK_BASE* areaBlock : areaWalker )
3057 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3060 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler );
3063 canonicalizeLayer( zone.get() );
3064 fp->Add( zone.release() );
3069 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3071 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3073 canonicalizeLayer( item.get() );
3088 fp->Add( item.release() );
3116 netCode = netIt->second->GetNetCode();
3136 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3138 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3142 PAD*
pad =
static_cast<PAD*
>( item.get() );
3143 pad->SetFPRelativeOrientation( padLocalRot );
3146 item->SetFPRelativePosition( padLocalPos );
3147 fp->Add( item.release() );
3165 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3171 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3181 const uint8_t segType = block->GetBlockType();
3193 int width =
static_cast<int>( segInfo.
m_Width );
3195 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3197 seg->SetNetCode( aNetCode );
3198 seg->SetLayer( layer );
3200 seg->SetStart(
scale( start ) );
3202 seg->SetWidth(
scale( width ) );
3204 items.push_back( std::move( seg ) );
3214 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3216 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3223 EDA_ANGLE angle = endAngle - startAngle;
3225 if( clockwise && angle <
ANGLE_0 )
3228 if( !clockwise && angle >
ANGLE_0 )
3234 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3236 arc->SetNetCode( aNetCode );
3237 arc->SetLayer( layer );
3239 arc->SetStart( start );
3242 arc->SetWidth( width );
3244 items.push_back( std::move( arc ) );
3266 static const std::regex spanRe( R
"((?:^|\D)(\d{1,2})-(\d{1,2})(?:\D|$))" );
3268 const std::string
name = aName.ToStdString();
3270 for( std::sregex_iterator it(
name.begin(),
name.end(), spanRe ), last; it != last; ++it )
3272 const int begin = std::stoi( ( *it )[1].str() );
3273 const int end = std::stoi( ( *it )[2].str() );
3275 if( begin >= 1 && begin <
end &&
end <= aTotalCu && (
end - begin + 1 ) == aSpanLen )
3289 int aTotalCu,
bool& aResolved )
3297 const int spanLen =
static_cast<int>( aPadstack.
GetLayerCount() );
3299 if( spanLen <= 1 || spanLen >= aTotalCu )
3300 return std::nullopt;
3309 return std::make_pair( begin - 1,
end - 1 );
3323 const auto& [minCu, maxCu] = it->second;
3326 if( maxCu > minCu && ( maxCu - minCu + 1 ) == spanLen )
3327 return std::make_pair( minCu, maxCu );
3334 wxString::Format(
"Via padstack '%s' crosses %d of %d copper layers but its span could "
3335 "not be determined; importing as a through via.",
3336 name, spanLen, aTotalCu ),
3339 return std::nullopt;
3345 const int totalCu =
m_board.GetCopperLayerCount();
3347 auto record = [
this]( int32_t aX, int32_t aY,
int aCopper )
3353 it->second.first = std::min( it->second.first, aCopper );
3354 it->second.second = std::max( it->second.second, aCopper );
3370 for(
const BLOCK_BASE* connItemBlock : connWalker )
3372 if( connItemBlock->GetBlockType() != 0x05 )
3383 if( copper < 0 || copper >= totalCu )
3388 for(
const BLOCK_BASE* segBlock : segWalker )
3390 switch( segBlock->GetBlockType() )
3397 record( seg.m_StartX, seg.m_StartY, copper );
3398 record( seg.m_EndX, seg.m_EndY, copper );
3405 record( arc.m_StartX, arc.m_StartY, copper );
3406 record( arc.m_EndX, arc.m_EndY, copper );
3431 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3432 via->SetPosition(
scale( viaPos ) );
3433 via->SetNetCode( aNetCode );
3449 const int totalCu =
m_board.GetCopperLayerCount();
3451 std::optional<std::pair<int, int>> span;
3455 span = cacheIt->second;
3459 bool resolved =
false;
3460 span =
resolveViaSpan( *viaPadstack, viaPos, totalCu, resolved );
3472 const bool touchesOuter = ( span->first == 0 ) || ( span->second == totalCu - 1 );
3489 viaDrill = viaWidth / 2;
3490 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3491 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack '%s' key %#010x, using fallback %d",
3497 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3499 "Via at (%d, %d) in padstack '%s' key %#010x has no valid pad component, using drill-based "
3500 "fallback (%d * 2)",
3502 viaWidth = viaDrill * 2;
3505 via->SetWidth(
F_Cu, viaWidth );
3506 via->SetDrill( viaDrill );
3516 std::vector<BOARD_ITEM*> newItems;
3521 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3533 const int netCode = netIt->second->GetNetCode();
3538 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3547 for(
const BLOCK_BASE* connItemBlock : connWalker )
3549 const uint8_t connType = connItemBlock->GetBlockType();
3553 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3561 newItemList =
buildTrack( trackData, netCode );
3567 newItemList.push_back(
buildVia( viaData, netCode ) );
3597 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3599 newItems.push_back( newItem.get() );
3606 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() )
3639 newItems.push_back( std::move( rectShape ) );
3652 for(
auto& shapeItem : shapeItems )
3653 newItems.push_back( std::move( shapeItem ) );
3658 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3668 for(
const BLOCK_BASE* block : outline2Walker )
3672 switch( block->GetBlockType() )
3682 newItems.push_back( std::move( rectShape ) );
3693 newItems.push_back( std::move( rectShape ) );
3705 for(
auto& shapeItem : shapeItems )
3706 newItems.push_back( std::move( shapeItem ) );
3711 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3729 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3731 for(
auto& item : graphicItems )
3732 newItems.push_back( std::move( item ) );
3737 std::vector<BOARD_ITEM*> addedItems;
3738 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3740 addedItems.push_back( item.get() );
3744 m_board.FinalizeBulkAdd( addedItems );
3755 return cacheIt->second;
3758 uint32_t currentKey = aStartKey;
3761 static constexpr int MAX_CHAIN_LENGTH = 50000;
3764 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3785 outline.
Append( shapeArc );
3789 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3796 EDA_ANGLE arcAngle = endAngle - startAngle;
3798 if( clockwise && arcAngle <
ANGLE_0 )
3801 if( !clockwise && arcAngle >
ANGLE_0 )
3808 outline.
Append( shapeArc );
3811 currentKey = arc.m_Next;
3826 currentKey = seg.m_Next;
3845 VECTOR2I topRight{ botRight.x, topLeft.
y };
3846 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3848 outline.
Append( topLeft );
3849 outline.
Append( topRight );
3850 outline.
Append( botRight );
3851 outline.
Append( botLeft );
3854 outline.
Rotate( angle, topLeft );
3866 VECTOR2I topRight{ botRight.x, topLeft.
y };
3867 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3869 outline.
Append( topLeft );
3870 outline.
Append( topRight );
3871 outline.
Append( botRight );
3872 outline.
Append( botLeft );
3875 outline.
Rotate( angle, topLeft );
3886 for(
const BLOCK_BASE* segBlock : segWalker )
3888 switch( segBlock->GetBlockType() )
3900 outline.
Append( shapeArc );
3904 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3911 EDA_ANGLE arcAngle = endAngle - startAngle;
3913 if( clockwise && arcAngle <
ANGLE_0 )
3916 if( !clockwise && arcAngle >
ANGLE_0 )
3923 outline.
Append( shapeArc );
3944 segBlock->GetBlockType() );
3970 while( holeKey != 0 )
3984 polySet.
AddHole( holeOutline );
3987 holeKey = keepout.m_Next;
4005 chain.SetClosed(
true );
4015 chain.SetClosed(
true );
4025 chain.SetClosed(
true );
4045 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
4078 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
4087 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
4092 auto zone = std::make_unique<ZONE>( &
m_board );
4097 zone->SetLayer( layer );
4110 zone->SetIsRuleArea(
true );
4111 zone->SetLayerSet( layerSet );
4112 zone->SetDoNotAllowTracks( isRouteKeepout );
4113 zone->SetDoNotAllowVias( isViaKeepout );
4114 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
4115 zone->SetDoNotAllowPads(
false );
4116 zone->SetDoNotAllowFootprints( isPackageKeepout );
4122 zone->SetZoneName(
"Route Keepin" );
4123 else if( isPackageKeepin )
4124 zone->SetZoneName(
"Package Keepin" );
4129 for(
const BLOCK_BASE* block : aRelatedBlocks )
4134 switch( block->GetBlockType() )
4138 const auto it =
m_netCache.find( block->GetKey() );
4143 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
4145 netCode = it->second->GetNetCode();
4149 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
4150 block->GetKey(), aBoundaryBlock.
GetKey() ),
4160 combinedFill.
Append( fillPolySet );
4170 zone->SetNetCode( netCode );
4176 if( isCopperZone && !combinedFill.
IsEmpty() )
4190 zone->SetIsFilled(
true );
4191 zone->SetNeedRefill(
false );
4204 std::vector<const BLOCK_BASE*> ret;
4217 if( !ptrArray || ptrArray->
m_Count == 0 )
4220 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4221 ret.resize( count );
4223 for(
size_t i = 0; i < count; i++ )
4244 if( strWrapper.GetGroupPtr() != 0 )
4252 text->GetPosition().x,
text->GetPosition().y );
4262template <std::derived_from<BOARD_ITEM> T>
4265 std::vector<BOARD_ITEM*> rawPointers;
4266 rawPointers.reserve( aItems.size() );
4268 for( std::unique_ptr<T>& item : aItems )
4270 rawPointers.push_back( item.get() );
4282 std::vector<std::unique_ptr<ZONE>> newZones;
4283 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4293 std::unique_ptr<ZONE> zone;
4296 switch( block->GetBlockType() )
4305 zone =
buildZone( *block, {}, zoneFillHandler );
4316 zone =
buildZone( *block, {}, zoneFillHandler );
4328 layerInfo = shapeData.
m_Layer;
4333 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4334 block->GetBlockType(), block->GetKey() );
4341 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4342 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4343 layerInfo.m_Subclass );
4345 newZones.push_back( std::move( zone ) );
4352 for(
const BLOCK_BASE* block : keepoutWalker )
4354 std::unique_ptr<ZONE> zone;
4356 switch( block->GetBlockType() )
4368 zone =
buildZone( *block, {}, zoneFillHandler );
4381 zone =
buildZone( *block, {}, zoneFillHandler );
4390 newZones.push_back( std::move( zone ) );
4397 int originalCount = newZones.size();
4406 int mergedCount = mergedZones.size();
4408 int keepoutCount = 0;
4409 int boundaryCount = 0;
4411 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4413 if( zone->GetIsRuleArea() )
4421 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4422 keepoutCount, originalCount - mergedCount );
4439 const wxString& tableName =
m_brdDb.GetString( tableData.m_StringPtr );
4441 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4445 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4447 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4448 tableData.m_Key, tableData.m_Ptr1 );
4452 wxLogTrace(
traceAllegroBuilder,
" Key table pointer %#010x is invalid", tableData.m_Ptr1 );
4456 switch( keyTable->GetBlockType() )
4462 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4464 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4466 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4468 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4483 newItems.push_back( std::move( newItem ) );
4500 keyTable->GetBlockType() );
4506 if( newItems.size() > 0 )
4508 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4510 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4511 group->SetName( tableName );
4513 for(
const auto& item : newItems )
4514 group->AddItem( item.get() );
4516 newItems.push_back( std::move(
group ) );
4539 int copperShapeCount = 0;
4540 int teardropCount = 0;
4555 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4557 if( isDynCopperShape )
4559 auto 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();
4583 shape->SetPolyShape( fractured );
4584 shape->SetFilled(
true );
4585 shape->SetLayer( fill.layer );
4586 shape->SetNetCode( fill.netCode );
4595 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4596 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4602 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4606 if( zone->IsTeardropArea() )
4607 teardropsByNet[zone->GetNetCode()].push_back( zone );
4610 if( teardropsByNet.empty() )
4618 for(
PAD*
pad : fp->Pads() )
4620 auto it = teardropsByNet.find(
pad->GetNetCode() );
4622 if( it == teardropsByNet.end() )
4625 for(
ZONE* tdZone : it->second )
4632 pad->SetTeardropsEnabled(
true );
4646 auto it = teardropsByNet.find(
via->GetNetCode() );
4648 if( it == teardropsByNet.end() )
4651 for(
ZONE* tdZone : it->second )
4658 via->SetTeardropsEnabled(
true );
4665 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4673 static_cast<int>(
m_brdDb.m_FmtVer ),
4676 m_brdDb.m_Header->m_AllegroVersion.data() );
4749 std::vector<BOARD_ITEM*> bulkAddedItems;
4751 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4758 [
this, &fpBlock]( uint8_t aType,
const BLOCK_BASE& )
4760 m_reporter.Report( wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4761 aType, fpBlock.m_Key ),
4771 bulkAddedItems.push_back( fp.get() );
4776 m_reporter.Report( wxString::Format(
"Failed to construct footprint for 0x2D key %#010x", inst.m_Key ),
4785 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4786 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4788 if( !bulkAddedItems.empty() )
4789 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)
static int64_t packPoint(int32_t aX, int32_t aY)
Pack an x/y coordinate pair into a unique key.
#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 bool parseViaSpanFromName(const wxString &aName, int aSpanLen, int aTotalCu, int &aBegin, int &aEnd)
Parse a 1-based "<begin>-<end>" copper layer span from an Allegro padstack name (e....
static int clampForScale(double aValue)
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.
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
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.
std::unique_ptr< PCB_SHAPE > buildArc(const BLK_0x01_ARC &aArc, const LAYER_INFO &aLayerInfo, PCB_LAYER_ID aLayer, BOARD_ITEM_CONTAINER &aParent)
std::unordered_map< uint32_t, std::optional< std::pair< int, int > > > m_viaSpanCache
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()
std::unordered_map< int64_t, std::pair< int, int > > m_trackEndpointCopper
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
bool m_trackEndpointsCollected
void collectTrackEndpointCopper()
Populate m_trackEndpointCopper, mapping each copper track segment endpoint to the copper layers termi...
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::optional< std::pair< int, int > > resolveViaSpan(const BLK_0x1C_PADSTACK &aPadstack, const VECTOR2I &aViaCenterRaw, int aTotalCu, bool &aResolved)
Resolve a via padstack's copper span (0-based first/last copper index), or nullopt for a through via,...
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...
Information pertinent to a Pcbnew printed circuit board.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void FinalizeBulkAdd(std::vector< BOARD_ITEM * > &aNewItems)
Must be used if Add() is used using a BULK_x ADD_MODE to generate a change event for listeners.
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
virtual void SetFilled(bool aFlag)
virtual void SetVisible(bool aVisible)
virtual void SetText(const wxString &aText)
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & AllLayersMask()
A collection of nets and the parameters used to route or test these nets.
static const char Default[]
the name of the default NETCLASS
int GetDiffPairGap() const
bool HasDiffPairWidth() const
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
bool HasTrackWidth() const
int GetDiffPairWidth() const
bool HasDiffPairGap() const
int GetTrackWidth() const
bool HasClearance() const
Handle the data for a net.
const wxString & GetNetname() const
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
COPPER_LAYER_PROPS & CopperLayer(PCB_LAYER_ID aLayer)
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
void SetLayerSet(const LSET &aSet)
static LSET PTHMask()
layer set for a through hole pad
static LSET UnplatedHoleMask()
layer set for a mechanical unplated through hole pad
static LSET SMDMask()
layer set for a SMD pad on Front layer
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
void Execute(ContainerT &aItems)
Call this to execute the task on all items in aItems, using the thread pool and dispatching the tasks...
PRIORITY_THREAD_POOL_TASK()
A small class to help profiling.
double msecs(bool aSinceLast=false)
A progress reporter interface for use in multi-threaded environments.
A pure virtual class used to derive REPORTER objects from.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
int TotalVertices() const
Return total number of vertices stored in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddPolygon(const POLYGON &apolygon)
Adds a polygon to the set.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const POLYGON & CPolygon(int aIndex) const
const std::vector< POLYGON > & CPolygons() const
Simple container to manage line stroke parameters.
Rate-limiter that fires at most once per interval.
const std::string Format() const
Return the vector formatted as a string.
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
SHAPE_POLY_SET * Outline()
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
const int minSize
Push and Shove router track width and via size dialog.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE FULL_CIRCLE
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
static const wxChar *const traceAllegroBuilder
Flag to enable debug output of Allegro board construction.
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
#define MAX_USER_DEFINED_LAYERS
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
@ LEFT_RIGHT
Flip left to right (around the Y axis)
@ THROW
THROW_IO_ERROR on mismatch.
@ LOG_TRACE
wxLogTrace the mismatch and skip
@ SKIP
silently skip blocks with the wrong type
@ 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.
@ 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
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.
Substruct in a padstack object.
uint32_t m_StrPtr
Seems to point to various things:
@ TYPE_CHAMFERED_RECTANGLE
COND_GE< FMT_VER::V_172, int32_t > m_Z1
This is all the info needed to do the fill of one layer of one zone.
SHAPE_POLY_SET m_CombinedFill
The wider filled area we will chop a piece out of for this layer of this zone.
The features of a padstack that can vary between copper layers All parameters are optional; leaving t...
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
size_t operator()(const LAYER_INFO &aLayerInfo) const noexcept
@ USER
The field ID hasn't been set yet; field is invalid.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
const SHAPE_LINE_CHAIN chain
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
std::vector< std::unique_ptr< ZONE > > MergeZonesWithSameOutline(std::vector< std::unique_ptr< ZONE > > &&aZones)
Merges zones with identical outlines and nets on different layers into single multi-layer zones.
@ FULL
pads are covered by copper