33#include <unordered_set>
73#define BLK_FIELD( BLK_T, FIELD ) BlockDataAs<BLK_T>( aBlock ).FIELD
86 wxString::Format(
"Unexpected next item in 0x32 pad list: block type %#04x, offset %#lx, key %#010x",
100 return ( aLayerInfo.m_Class << 8 ) + aLayerInfo.m_Subclass;
113static const std::unordered_map<LAYER_INFO, PCB_LAYER_ID>
s_LayerKiMap = {
197 static const std::unordered_map<uint8_t, wxString> s_ClassNames = {
220 static const std::unordered_map<uint8_t, wxString> s_BoardGeomSubclassNames = {
244 static const std::unordered_map<uint8_t, wxString> s_ComponentValueSubclassNames = {
253 static const std::unordered_map<uint8_t, wxString> s_DrawingFormatSubclassNames = {
261 static const std::unordered_map<uint8_t, wxString> s_PackageGeometrySubclassNames = {
281 static const std::unordered_map<uint8_t, wxString> s_ManufacturingSubclassNames = {
298 static const std::unordered_map<uint8_t, wxString> s_AnalysisSubclassNames = {
307 static const std::unordered_map<uint8_t, wxString> s_ConstraintSubclassNames = {
311 static const std::unordered_map<uint8_t, wxString> s_KeepinSubclassNames = {
315 static const std::unordered_map<uint8_t, wxString> s_KeepoutSubclassNames = {
321 static const std::unordered_map<uint8_t, const std::unordered_map<uint8_t, wxString>&> s_SubclassNameMaps = {
345 const auto classIt = s_ClassNames.find( aLayerInfo.
m_Class );
347 if( classIt != s_ClassNames.end() )
348 className = classIt->second;
350 className = wxString::Format( wxS(
"Class_%02X" ), aLayerInfo.
m_Class );
352 wxString subclassName;
355 auto classMapIt = s_SubclassNameMaps.find( aLayerInfo.
m_Class );
357 if( classMapIt != s_SubclassNameMaps.end() )
359 const std::unordered_map<uint8_t, wxString>& subclassMap = classMapIt->second;
361 const auto subIt = subclassMap.find( aLayerInfo.
m_Subclass );
363 if( subIt != subclassMap.end() )
364 subclassName = subIt->second;
368 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
374 subclassName = wxString::Format( wxS(
"Subclass_%02X" ), aLayerInfo.
m_Subclass );
377 return className + wxS(
"/" ) + subclassName;
420 return trace.m_Layer;
430 return shape.m_Layer;
448 wxCHECK( layerInfo.has_value(),
LAYER_INFO() );
450 return layerInfo.value();
460 if( aIndex >= aTotal - 1 )
471 return (
static_cast<int64_t
>(
static_cast<uint32_t
>( aX ) ) << 32 )
472 |
static_cast<uint32_t
>( aY );
504 if(
m_Lists.count( &aList ) == 0 )
506 std::vector<CUSTOM_LAYER>& classLayers =
m_Lists[&aList];
512 const wxString& layerName =
m_brdDb.GetString( entry.mLayerNameId );
521 classLayers.emplace_back(
CUSTOM_LAYER( entry.m_Name ) );
531 classLayers.size(), aClass, aList.
m_Key );
553 const std::vector<CUSTOM_LAYER>& etchLayers = *customLayerIt->second;
554 const size_t numCuLayers = etchLayers.size();
556 m_board.GetDesignSettings().SetCopperLayerCount( numCuLayers );
558 std::vector<INPUT_LAYER_DESC> inputLayers;
560 for(
size_t li = 0; li < numCuLayers; ++li )
563 desc.
Name = etchLayers[li].m_Name;
567 inputLayers.push_back( desc );
572 int nextAutoUser = 0;
579 for(
size_t si = 0; si < layerList->size(); ++si )
581 const LAYER_INFO li{ classId,
static_cast<uint8_t
>( si ) };
590 if( layerList->at( si ).m_Name.length() > 0 )
591 desc.
Name = layerList->at( si ).m_Name;
596 inputLayers.push_back( desc );
607 desc.
Name = layerName;
611 inputLayers.push_back( desc );
621 inputLayers.push_back( desc );
627 for(
size_t li = 0; li < numCuLayers; ++li )
630 const wxString& layerName = etchLayers[li].m_Name;
632 auto it = resolvedMapping.find( layerName );
633 PCB_LAYER_ID lId = ( it != resolvedMapping.end() ) ? it->second
637 m_board.SetLayerName( lId, layerName );
641 for(
const auto& [layerInfo, defaultKiLayer] :
s_LayerKiMap )
645 auto rmIt = resolvedMapping.find( displayName );
656 auto rmIt = resolvedMapping.find( dialogName );
661 m_board.SetLayerName( rmIt->second, dialogName );
666 LSET enabledLayersMask =
m_board.GetEnabledLayers();
668 for(
const auto& [
name, layerId] : resolvedMapping )
671 enabledLayersMask |=
LSET{ layerId };
677 m_board.GetLayerName( layerId ), layerId );
681 m_board.SetEnabledLayers( enabledLayersMask );
683 m_board.GetDesignSettings().SetUserDefinedLayerCount( userLayers );
708 && cLayerList == etchIt->second
709 && aLayerInfo.
m_Subclass < cLayerList->size() )
717 if( aLayerInfo.
m_Subclass < cLayerList->size() )
769 const wxString
name = aTop ?
"PLACE_BOUND_TOP" :
"PLACE_BOUND_BOTTOM";
857 wxLogTrace(
traceAllegroBuilder,
" Unhandled non-copper zone layer class %#02x, using default layers",
900 m_board.GetDesignSettings().SetUserDefinedLayerCount(
m_board.GetDesignSettings().GetUserDefinedLayerCount() + 1 );
901 m_board.SetLayerName( lId, aName );
908 std::unordered_map<const BLK_0x2A_LAYER_LIST*, std::vector<CUSTOM_LAYER>>
m_Lists;
971 if(
m_brdDb.m_Header->m_UnitsDivisor == 0 )
974 if( !c_baseScales.contains(
m_brdDb.m_Header->m_BoardUnits ) )
977 double baseScale( c_baseScales.at(
m_brdDb.m_Header->m_BoardUnits ) );
1060 wxLogTrace(
traceAllegroPerf, wxT(
" Intersected and fractured zone fills in %.3f ms" ),
1070 m_FillInfos.emplace_back( &aZone, aLayer, std::move( aFilledArea ) );
1085 double result = std::round( aValue );
1087 if(
result > std::numeric_limits<int>::max() )
1088 return std::numeric_limits<int>::max();
1090 if(
result < std::numeric_limits<int>::min() )
1091 return std::numeric_limits<int>::min();
1093 return static_cast<int>(
result );
1128 m_reporter.Report( wxString::Format(
"Could not find expected block with key %#010x and type %#04x", aKey, aType ),
1134 const wxString& aName )
const
1136 wxString
name = aName.IsEmpty() ? wxString(
"Object" ) : aName;
1137 wxString withKey = ( aKey == 0 ) ? wxString(
"" ) : wxString::Format(
", with key %#010x ", aKey );
1138 wxString withOffset = ( aOffset == 0 ) ? wxString(
"" ) : wxString::Format(
", at offset %#zx ", aOffset );
1140 wxString s = wxString::Format(
"%s has unexpected type %#04x (expected %#04x)%s%s",
name, aGot, aExpected, withKey,
1151 if( blk0x30 ==
nullptr )
1156 if( blk0x31 ==
nullptr )
1168 bool encountered =
false;
1172 if( blk0x36.m_Code != 0x08 )
1183 for(
const auto& item : blk0x36.m_Items )
1185 const auto& fontDef = std::get<BLK_0x36_DEF_TABLE::FontDef_X08>( item );
1201 std::vector<BOARD_ITEM*> bulkAdded;
1204 m_brdDb.m_Header->m_LL_0x1B_Nets,
1211 wxString netName =
m_brdDb.GetString( netBlk.m_NetName );
1216 if( netName.IsEmpty() )
1217 netName = wxString::Format( wxS(
"Net_%d" ), netCode );
1219 auto kiNetInfo = std::make_unique<NETINFO_ITEM>( &
m_board, netName, netCode );
1223 bulkAdded.push_back( kiNetInfo.get() );
1227 m_board.FinalizeBulkAdd( bulkAdded );
1237 if( !fieldBlock || fieldBlock->
GetBlockType() != 0x03 )
1238 return wxEmptyString;
1241 const std::string* str = std::get_if<std::string>( &field.
m_Substruct );
1244 return wxEmptyString;
1248 size_t sep = str->find(
":\\" );
1250 if( sep == std::string::npos )
1251 return wxEmptyString;
1253 std::string extracted = str->substr( sep + 2 );
1255 if( !extracted.empty() && extracted.back() ==
'\\' )
1256 extracted.pop_back();
1258 return wxString( extracted );
1267 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1276 int diffPairGap = 0;
1280 std::map<wxString, CS_DEF> constraintSets;
1283 std::map<uint32_t, wxString> keyToSetName;
1291 const wxString& resolved =
m_brdDb.GetString( csBlock.m_NameStrKey );
1293 if( !resolved.IsEmpty() )
1297 else if( csBlock.m_FieldPtr != 0 )
1303 if( setName.IsEmpty() )
1304 setName = wxString::Format( wxS(
"CS_%d" ), csIndex );
1308 if( csBlock.m_DataB.empty() )
1310 wxLogTrace(
traceAllegroBuilder,
"Constraint set '%s' has no DataB records, skipping", setName );
1315 const auto& record = csBlock.m_DataB[0];
1317 static_assert(
sizeof( fields ) == std::tuple_size_v<std::decay_t<
decltype( record )>> );
1318 memcpy( fields, record.data(),
sizeof( fields ) );
1325 def.lineWidth =
scale( fields[1] );
1326 def.clearance =
scale( fields[4] );
1332 def.lineWidth =
scale( fields[0] );
1333 def.clearance =
scale( fields[1] );
1336 def.diffPairGap =
scale( fields[7] );
1338 constraintSets[setName] = def;
1339 keyToSetName[csBlock.m_NameStrKey] = setName;
1342 "Constraint set '%s': line_width=%d nm, clearance=%d nm, dp_gap=%d nm",
1343 setName, def.lineWidth, def.clearance, def.diffPairGap );
1346 if( constraintSets.empty() )
1353 for(
const auto& [
name, def] : constraintSets )
1355 wxString ncName =
name;
1358 ncName = wxS(
"Allegro_Default" );
1360 if( netSettings->HasNetclass( ncName ) )
1363 auto nc = std::make_shared<NETCLASS>( ncName );
1365 if( def.lineWidth > 0 )
1366 nc->SetTrackWidth( def.lineWidth );
1368 if( def.clearance > 0 )
1369 nc->SetClearance( def.clearance );
1371 if( def.diffPairGap > 0 )
1373 nc->SetDiffPairGap( def.diffPairGap );
1376 if( def.lineWidth > 0 )
1377 nc->SetDiffPairWidth( def.lineWidth );
1380 netSettings->SetNetclass( ncName, nc );
1386 wxString defaultSetName;
1388 for(
const auto& [
name, def] : constraintSets )
1390 if(
name.CmpNoCase( wxS(
"DEFAULT" ) ) == 0 )
1392 defaultSetName =
name;
1406 wxString assignedSetName;
1408 if( csField.has_value() )
1410 if(
auto* intVal = std::get_if<uint32_t>( &csField.value() ) )
1412 auto it = keyToSetName.find( *intVal );
1414 if( it != keyToSetName.end() )
1415 assignedSetName = it->second;
1417 else if(
auto* strVal = std::get_if<wxString>( &csField.value() ) )
1419 if( constraintSets.count( *strVal ) )
1420 assignedSetName = *strVal;
1425 if( assignedSetName.IsEmpty() && !defaultSetName.IsEmpty() )
1426 assignedSetName = defaultSetName;
1428 if( assignedSetName.IsEmpty() )
1431 wxString ncName = assignedSetName;
1434 ncName = wxS(
"Allegro_Default" );
1436 if( !netSettings->HasNetclass( ncName ) )
1439 auto netIt =
m_netCache.find( netBlk.m_Key );
1445 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1446 kiNet->
SetNetClass( netSettings->GetNetClassByName( ncName ) );
1449 wxLogTrace(
traceAllegroBuilder,
"Applied %zu physical constraint sets", constraintSets.size() );
1458 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1462 std::map<int, std::vector<uint32_t>> widthToNetKeys;
1468 std::optional<int> minWidth =
1471 if( !minWidth.has_value() || minWidth.value() <= 0 )
1474 int widthNm =
scale( minWidth.value() );
1475 widthToNetKeys[widthNm].push_back( netBlk.m_Key );
1478 if( widthToNetKeys.empty() )
1484 for(
const auto& [widthNm, netKeys] : widthToNetKeys )
1486 int widthMils = ( widthNm + 12700 ) / 25400;
1487 wxString ncName = wxString::Format( wxS(
"W%dmil" ), widthMils );
1489 if( netSettings->HasNetclass( ncName ) )
1492 auto nc = std::make_shared<NETCLASS>( ncName );
1493 nc->SetTrackWidth( widthNm );
1494 netSettings->SetNetclass( ncName, nc );
1496 for( uint32_t netKey : netKeys )
1504 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1508 wxLogTrace(
traceAllegroBuilder,
"Created netclass '%s' (track width %d nm) with %zu nets",
1509 ncName, widthNm, netKeys.size() );
1512 wxLogTrace(
traceAllegroBuilder,
"Applied trace width constraints from %zu unique width groups",
1513 widthToNetKeys.size() );
1520 return wxEmptyString;
1525 return wxEmptyString;
1527 uint32_t tableKey = 0;
1533 tableKey = x26.m_GroupPtr;
1540 if(
next &&
next->GetBlockType() == 0x26 )
1543 tableKey = x26b.m_GroupPtr;
1554 return wxEmptyString;
1558 return wxEmptyString;
1564 if( !tableBlock || tableBlock->
GetBlockType() != 0x2C )
1565 return wxEmptyString;
1570 return wxEmptyString;
1574 wxLogTrace(
traceAllegroBuilder,
"Resolving match group name for NET '%s': found table at key %#010x, subtype %#x, name '%s'",
1583 wxLogTrace(
traceAllegroBuilder,
"Applying match group / differential pair assignments" );
1586 std::shared_ptr<NET_SETTINGS> netSettings = bds.
m_NetSettings;
1589 std::map<wxString, std::vector<uint32_t>> groupToNetKeys;
1597 if( groupName.empty() )
1600 groupToNetKeys[groupName].push_back( netBlk.m_Key );
1603 if( groupToNetKeys.empty() )
1612 for(
const auto& [groupName, netKeys] : groupToNetKeys )
1616 bool isDiffPair = ( netKeys.size() == 2 );
1617 wxString ncPrefix = isDiffPair ? wxS(
"DP_" ) : wxS(
"MG_" );
1618 wxString ncName = ncPrefix + groupName;
1620 if( netSettings->HasNetclass( ncName ) )
1623 auto nc = std::make_shared<NETCLASS>( ncName );
1627 for( uint32_t netKey : netKeys )
1634 NETCLASS* existing = it->second->GetNetClass();
1654 netSettings->SetNetclass( ncName, nc );
1656 for( uint32_t netKey : netKeys )
1664 netSettings->SetNetclassPatternAssignment( kiNet->
GetNetname(), ncName );
1674 isDiffPair ? wxS(
"Diff pair" ) : wxS(
"Match" ),
1675 groupName, ncName, netKeys.size() );
1679 "Applied match groups: %d diff pairs, %d match groups (%zu total groups)",
1680 dpCount, mgCount, groupToNetKeys.size() );
1699 std::unordered_set<LAYER_INFO> layersFound;
1701 const auto& addLayer = [&]( std::optional<LAYER_INFO>&
info )
1703 if(
info.has_value() )
1705 layersFound.insert( std::move(
info.value() ) );
1719 simpleWalker( aDb.
m_Header->m_LL_Shapes );
1720 simpleWalker( aDb.
m_Header->m_LL_0x24_0x28 );
1721 simpleWalker( aDb.
m_Header->m_LL_0x14 );
1731 const auto& layerMap =
m_brdDb.m_Header->m_LayerMap;
1733 for(
size_t i = 0; i < layerMap.size(); ++i )
1735 const uint8_t classNum =
static_cast<uint8_t
>( i );
1737 const uint32_t x2aKey = layerMap[i].m_LayerList0x2A;
1766 if( layersFound.count( outlineInfo ) && layersFound.count( designOutlineInfo ) )
1770 "Both OUTLINE and DESIGN_OUTLINE layers found, remapping DESIGN_OUTLINE to a user layer" );
1783 wxString::Format(
"Font def index %u requested, have %zu entries", aIndex,
m_fontDefList.size() ),
1809 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1810 shape->SetLayer( aLayer );
1811 shape->SetStart( start );
1812 shape->SetEnd(
end );
1815 int adjustedWidth = width;
1817 if( adjustedWidth <= 0 )
1818 adjustedWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1820 shape->SetWidth( adjustedWidth );
1833 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::ARC );
1835 shape->SetLayer( aLayer );
1840 start.Format(),
end.Format() );
1843 start =
scale( start );
1850 bool clockwise = ( aArc.
m_SubType & 0x40 ) != 0;
1856 arcWidth =
m_board.GetDesignSettings().GetLineThickness( aLayer );
1858 shape->SetWidth( arcWidth );
1864 shape->SetCenter( c );
1865 shape->SetRadius(
radius );
1876 EDA_ANGLE angle = endangle - startangle;
1878 if( clockwise && angle <
ANGLE_0 )
1880 if( !clockwise && angle >
ANGLE_0 )
1889 shape->SetArcGeometry( start, mid,
end );
1899 std::unique_ptr<PCB_TEXT>
text = std::make_unique<PCB_TEXT>( &aParent );
1902 text->SetLayer( layer );
1908 m_reporter.Report( wxString::Format(
"Failed to find string graphic (0x31) with key %#010x "
1909 "in string wrapper (0x30) with key %#010x",
1917 if( aStrWrapper.
m_Font.has_value() )
1918 props = &aStrWrapper.
m_Font.value();
1920 if( !props && aStrWrapper.
m_Font16x.has_value() )
1926 wxString::Format(
"Expected one of the font properties fields in 0x30 object (key %#010x) to be set.",
1927 aStrWrapper.
m_Key ),
1943 text->SetTextAngle( textAngle );
1952 text->SetPosition( textPos + textFontOffset );
1955 text->SetMirrored(
true );
1980 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
1982 const uint32_t markerShape = aPinDef.
GetShape();
1988 const auto addLine = [&](
const SEG& aSeg )
1990 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::SEGMENT );
1991 shape->SetStart( aSeg.A );
1992 shape->SetEnd( aSeg.B );
1993 shapes.push_back( std::move( shape ) );
1996 const auto addPolyPts = [&](
const std::vector<VECTOR2I>& aPts )
1998 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::POLY );
1999 shape->SetPolyPoints( aPts );
2000 shapes.push_back( std::move( shape ) );
2003 switch( markerShape )
2007 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::CIRCLE );
2008 shape->SetCenter(
center );
2009 shape->SetRadius( size.x / 2 );
2010 shapes.push_back( std::move( shape ) );
2016 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2017 shape->SetStart(
center - size / 2 );
2018 shape->SetEnd(
center + size / 2 );
2019 shapes.push_back( std::move( shape ) );
2024 std::unique_ptr<PCB_SHAPE> shape;
2028 for(
const SEG& seg : segs )
2037 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent,
SHAPE_T::RECTANGLE );
2038 shape->SetStart(
center - size / 2 );
2039 shape->SetEnd(
center + size / 2 );
2041 int minSize = std::min( size.x, size.y );
2042 shape->SetCornerRadius(
minSize / 2 );
2043 shapes.push_back( std::move( shape ) );
2085 wxLogTrace(
traceAllegroBuilder,
"Unsupported drill marker shape type %#04x for pin definition with key %#010x",
2086 markerShape, aPinDef.
m_Key );
2091 std::vector<std::unique_ptr<BOARD_ITEM>> items;
2092 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2094 shape->SetLayer( layer );
2095 shape->SetWidth( 0 );
2097 items.push_back( std::move( shape ) );
2107 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
2121 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2123 newItems.push_back( std::move( shape ) );
2130 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphicContainer, aParent );
2131 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2132 newItems.push_back( std::move( shape ) );
2139 std::unique_ptr<PCB_SHAPE> shape =
buildRect( rect, aParent );
2141 newItems.push_back( std::move( shape ) );
2147 std::unique_ptr<PCB_SHAPE> shape =
buildPolygon( shapeData, aParent );
2149 newItems.push_back( std::move( shape ) );
2156 std::unique_ptr<BOARD_ITEM> newItem =
buildPcbText( strWrapper, aParent );
2158 newItems.push_back( std::move( newItem ) );
2181 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2195 for(
const BLOCK_BASE* segBlock : segWalker )
2197 std::unique_ptr<PCB_SHAPE> shape;
2199 switch( segBlock->GetBlockType() )
2218 segBlock->GetBlockType() );
2224 shapes.push_back( std::move( shape ) );
2233 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2236 shape->SetLayer( layer );
2243 shape->SetStart( cornerA );
2244 shape->SetEnd( cornerB );
2247 shape->Rotate( cornerA, angle );
2249 const int lineWidth = 0;
2250 shape->SetWidth( lineWidth );
2258 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2261 shape->SetLayer( layer );
2268 shape->SetStart( cornerA );
2269 shape->SetEnd( cornerB );
2272 shape->Rotate( cornerA, angle );
2274 const int lineWidth = 0;
2275 shape->SetWidth( lineWidth );
2283 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &aParent );
2286 shape->SetLayer( layer );
2292 if(
chain.PointCount() < 3 )
2294 wxLogTrace(
traceAllegroBuilder,
"Polygon (0x28) with key %#010x has fewer than 3 points, skipping",
2299 chain.SetClosed(
true );
2300 shape->SetPolyShape(
chain );
2302 const int lineWidth = 0;
2303 shape->SetWidth( lineWidth );
2312 std::vector<std::unique_ptr<PCB_SHAPE>> shapes;
2319 for(
const BLOCK_BASE* segBlock : segWalker )
2321 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( &
m_board );
2322 shape->SetLayer( layer );
2323 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2325 switch( segBlock->GetBlockType() )
2339 shape->SetCenter( c );
2340 shape->SetRadius(
radius );
2346 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
2354 EDA_ANGLE angle = endangle - startangle;
2356 if( clockwise && angle <
ANGLE_0 )
2359 if( !clockwise && angle >
ANGLE_0 )
2365 shape->SetArcGeometry( start, mid,
end );
2378 shape->SetStart( start );
2379 shape->SetEnd(
end );
2380 shape->SetWidth(
m_board.GetDesignSettings().GetLineThickness( layer ) );
2384 wxLogTrace(
traceAllegroBuilder,
" Unhandled segment type in outline: %#04x", segBlock->GetBlockType() );
2388 shapes.push_back( std::move( shape ) );
2397 uint32_t refKey = 0x00;
2415 FOOTPRINT& aFp,
const wxString& aPadName,
int aNetcode )
2421 std::vector<std::unique_ptr<BOARD_ITEM>> padItems;
2423 std::vector<std::unique_ptr<PADSTACK::COPPER_LAYER_PROPS>> copperLayers( aPadstack.
GetLayerCount() );
2426 std::optional<int> thermalGap;
2428 const wxString& padStackName =
m_brdDb.GetString( aPadstack.
m_PadStr );
2447 wxString::Format(
"Padstack %s: Copper layer %zu has no pad component, but has antipad",
2454 wxString::Format(
"Copper layer %zu has no pad component, but has thermal relief", i ),
2460 auto& layerCuProps = copperLayers[i];
2462 layerCuProps = std::make_unique<PADSTACK::COPPER_LAYER_PROPS>();
2495 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2496 layerCuProps->shape.round_rect_radius_ratio = padComp.
m_Z1.value() / (double) minDim;
2498 layerCuProps->shape.round_rect_radius_ratio = 0.25;
2510 if( padComp.
m_Z1.has_value() && padComp.
m_Z1.value() > 0 && minDim > 0 )
2511 layerCuProps->shape.chamfered_rect_ratio = padComp.
m_Z1.value() / (double) minDim;
2513 layerCuProps->shape.chamfered_rect_ratio = 0.25;
2525 layerCuProps->shape.chamfered_rect_ratio = 1.0 - 1.0 / sqrt( 2.0 );
2538 "Padstack %s: SHAPE_SYMBOL on layer %zu has no 0x28 shape at %#010x",
2539 padStackName, i, padComp.
m_StrPtr );
2554 int anchorSize =
static_cast<int>(
2557 if( anchorSize < 1 )
2560 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2562 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2564 poly->SetFilled(
true );
2565 poly->SetWidth( 0 );
2566 layerCuProps->custom_shapes.push_back( poly );
2571 "Padstack %s: SHAPE_SYMBOL on layer %zu produced only %d points",
2583 const int w = std::max( padComp.
m_W, 300 );
2584 const int h = std::max( padComp.
m_H, 220 );
2587 auto S = [&](
int x,
int y )
2593 outline.
Append(
S( 0, -h / 2 ) );
2594 outline.
Append(
S( w / 2, -h / 6 ) );
2595 outline.
Append(
S( w / 3, h / 2 ) );
2596 outline.
Append(
S( -w / 3, h / 2 ) );
2597 outline.
Append(
S( -w / 2, -h / 6 ) );
2601 int anchorSize =
static_cast<int>(
2604 if( anchorSize < 1 )
2607 layerCuProps->shape.size =
VECTOR2I( anchorSize, anchorSize );
2609 auto poly = std::make_shared<PCB_SHAPE>(
nullptr,
SHAPE_T::POLY );
2611 poly->SetFilled(
true );
2612 poly->SetWidth( 0 );
2613 layerCuProps->custom_shapes.push_back( poly );
2618 wxString::Format(
"Padstack %s: unhandled copper pad shape type %d on layer %zu",
2619 padStackName,
static_cast<int>( padComp.
m_Type ), i ),
2629 "differs from pad shape %d",
2633 int clearanceX =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2634 int clearanceY =
scale( ( antiPadComp.
m_H - padComp.
m_H ) / 2 );
2636 if( clearanceX && clearanceX != clearanceY )
2639 "clearance X=%d Y=%d",
2640 padStackName, i, clearanceX, clearanceY );
2643 if( antiPadComp.
m_X3 != 0 || antiPadComp.
m_X4 != 0 )
2647 padStackName, i, antiPadComp.
m_X3, antiPadComp.
m_X4 );
2650 layerCuProps->clearance = clearanceX;
2659 int gap =
scale( ( antiPadComp.
m_W - padComp.
m_W ) / 2 );
2666 "Padstack %s: thermal relief type=%d, gap=%snm",
2667 padStackName, thermalComp.
m_Type,
2668 thermalGap.has_value() ? wxString::Format(
"%d", thermalGap.value() )
2669 : wxString(
"N/A" ) );
2679 if( copperLayers.size() == 0 )
2685 const auto layersEqual = [&](
size_t aFrom,
size_t aTo) ->
bool
2688 for(
size_t i = aFrom + 1; i < aTo; ++i )
2690 if( !copperLayers[i - 1] || !copperLayers[i] || *copperLayers[i - 1] != *copperLayers[i] )
2699 for(
size_t i = 0; i < copperLayers.size(); ++i )
2701 wxLogTrace(
traceAllegroBuilder,
" Layer %zu: %s", i, copperLayers[i] ?
"present" :
"null" );
2706 if( copperLayers.front() && copperLayers.back() && layersEqual( 0, copperLayers.size() ) )
2711 layerProps = *copperLayers.front();
2713 else if( copperLayers.front() && copperLayers.back()
2714 && layersEqual( 1, copperLayers.size() - 1 ) )
2716 wxLogTrace(
traceAllegroBuilder,
" Using FRONT_INNER_BACK padstack mode (inner layers identical)" );
2722 if( copperLayers.size() > 2 && copperLayers[1] )
2730 for(
size_t i = 0; i < copperLayers.size(); ++i )
2732 if( !copperLayers[i] )
2736 static_cast<int>( copperLayers.size() ) );
2757 if( std::holds_alternative<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header ) )
2759 const auto& hdr16x = std::get<BLK_0x1C_PADSTACK::HEADER_v16x>( aPadstack.
m_Header );
2761 if( hdr16x.m_SlotY > 0 )
2763 drillW =
scale(
static_cast<int>( hdr16x.m_SlotX ) );
2764 drillH =
scale(
static_cast<int>( hdr16x.m_SlotY ) );
2773 const auto& hdr17x = std::get<BLK_0x1C_PADSTACK::HEADER_v17x>( aPadstack.
m_Header );
2775 if( hdr17x.m_SlotY > 0 )
2777 drillW =
scale(
static_cast<int>( hdr17x.m_SlotX ) );
2778 drillH =
scale(
static_cast<int>( hdr17x.m_SlotY ) );
2782 drillW =
scale(
static_cast<int>( hdr17x.m_DrillSize ) );
2799 bool drillIsTaller = ( drillH > drillW );
2801 if( padIsTaller != drillIsTaller )
2802 std::swap( drillW, drillH );
2805 bool isSmd = ( drillW == 0 ) || ( aPadstack.
GetLayerCount() == 1 );
2815 if( drillW != drillH )
2821 std::unique_ptr<PAD>
pad = std::make_unique<PAD>( &aFp );
2822 pad->SetPadstack( padStack );
2823 pad->SetNumber( aPadName );
2824 pad->SetNetCode( aNetcode );
2842 if( thermalGap.has_value() )
2843 pad->SetThermalGap( thermalGap.value() );
2845 padItems.push_back( std::move(
pad ) );
2861 "Fixed padstack slot %zu: type=%d, W=%d, H=%d",
2862 i,
static_cast<int>( psComp.
m_Type ), psComp.
m_W, psComp.
m_H );
2871 auto fp = std::make_unique<FOOTPRINT>( &
m_board );
2875 const bool backSide = ( aFpInstance.
m_Layer != 0 );
2884 if( refDesStr.IsEmpty() )
2887 m_reporter.Report( wxString::Format(
"Empty ref des for 0x2D key %#010x", aFpInstance.
m_Key ),
2894 fp->SetReference( refDesStr );
2907 fp->SetPosition( fpPos );
2908 fp->SetOrientation( rotation );
2923 const auto canonicalizeLayer = [backSide, fpPos](
BOARD_ITEM* aItem )
2934 m_reporter.Report( wxString::Format(
"Unexpected type in graphics list: %#04x", aType ),
2940 std::vector<std::unique_ptr<PCB_SHAPE>> shapes =
buildShapes( graphics, *fp );
2942 for( std::unique_ptr<PCB_SHAPE>& shape : shapes )
2944 canonicalizeLayer( shape.get() );
2945 fp->Add( shape.release() );
2949 bool valueFieldSet =
false;
2961 canonicalizeLayer(
text.get() );
2963 const uint8_t textClass = strWrapper.m_Layer.m_Class;
2964 const uint8_t textSubclass = strWrapper.m_Layer.m_Subclass;
2977 if( !
text->GetText().IsEmpty() && !wxIsalpha(
text->GetText()[0] ) )
2978 text->SetText( wxString(
"UNK" ) +
text->GetText() );
2986 field->
SetText( wxS(
"${REFERENCE}" ) );
2992 if( !valueFieldSet )
2998 valueFieldSet =
true;
3033 fp->Add(
text.release() );
3040 for(
const BLOCK_BASE* assemblyBlock : assemblyWalker )
3042 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *assemblyBlock, *fp );
3044 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3046 canonicalizeLayer( item.get() );
3047 fp->Add( item.release() );
3057 for(
const BLOCK_BASE* areaBlock : areaWalker )
3061 if( layerInfo.has_value() &&
layerIsZone( *layerInfo ) )
3064 std::unique_ptr<ZONE> zone =
buildZone( *areaBlock, {}, zoneFillHandler );
3067 canonicalizeLayer( zone.get() );
3068 fp->Add( zone.release() );
3073 std::vector<std::unique_ptr<BOARD_ITEM>> shapes =
buildGraphicItems( *areaBlock, *fp );
3075 for( std::unique_ptr<BOARD_ITEM>& item : shapes )
3077 canonicalizeLayer( item.get() );
3092 fp->Add( item.release() );
3120 netCode = netIt->second->GetNetCode();
3140 std::vector<std::unique_ptr<BOARD_ITEM>> padItems =
buildPadItems( *padStack, *fp, padName, netCode );
3142 for( std::unique_ptr<BOARD_ITEM>& item : padItems )
3146 PAD*
pad =
static_cast<PAD*
>( item.get() );
3147 pad->SetFPRelativeOrientation( padLocalRot );
3150 item->SetFPRelativePosition( padLocalPos );
3151 fp->Add( item.release() );
3169 std::vector<std::unique_ptr<BOARD_ITEM>> items;
3175 wxLogTrace(
traceAllegroBuilder,
"Skipping ANTI_ETCH track (class=%#04x, subclass=%#04x)",
3185 const uint8_t segType = block->GetBlockType();
3197 int width =
static_cast<int>( segInfo.
m_Width );
3199 std::unique_ptr<PCB_TRACK> seg = std::make_unique<PCB_TRACK>( &
m_board );
3201 seg->SetNetCode( aNetCode );
3202 seg->SetLayer( layer );
3204 seg->SetStart(
scale( start ) );
3206 seg->SetWidth(
scale( width ) );
3208 items.push_back( std::move( seg ) );
3218 int width =
scale(
static_cast<int>( arcInfo.
m_Width ) );
3220 bool clockwise = ( arcInfo.
m_SubType & 0x40 ) != 0;
3227 EDA_ANGLE angle = endAngle - startAngle;
3229 if( clockwise && angle <
ANGLE_0 )
3232 if( !clockwise && angle >
ANGLE_0 )
3238 std::unique_ptr<PCB_ARC> arc = std::make_unique<PCB_ARC>( &
m_board );
3240 arc->SetNetCode( aNetCode );
3241 arc->SetLayer( layer );
3243 arc->SetStart( start );
3246 arc->SetWidth( width );
3248 items.push_back( std::move( arc ) );
3270 static const std::regex spanRe( R
"((?:^|\D)(\d{1,2})-(\d{1,2})(?:\D|$))" );
3272 const std::string
name = aName.ToStdString();
3274 for( std::sregex_iterator it(
name.begin(),
name.end(), spanRe ), last; it != last; ++it )
3276 const int begin = std::stoi( ( *it )[1].str() );
3277 const int end = std::stoi( ( *it )[2].str() );
3279 if( begin >= 1 && begin <
end &&
end <= aTotalCu && (
end - begin + 1 ) == aSpanLen )
3293 int aTotalCu,
bool& aResolved )
3301 const int spanLen =
static_cast<int>( aPadstack.
GetLayerCount() );
3303 if( spanLen <= 1 || spanLen >= aTotalCu )
3304 return std::nullopt;
3313 return std::make_pair( begin - 1,
end - 1 );
3327 const auto& [minCu, maxCu] = it->second;
3330 if( maxCu > minCu && ( maxCu - minCu + 1 ) == spanLen )
3331 return std::make_pair( minCu, maxCu );
3338 wxString::Format(
"Via padstack '%s' crosses %d of %d copper layers but its span could "
3339 "not be determined; importing as a through via.",
3340 name, spanLen, aTotalCu ),
3343 return std::nullopt;
3349 const int totalCu =
m_board.GetCopperLayerCount();
3351 auto record = [
this]( int32_t aX, int32_t aY,
int aCopper )
3357 it->second.first = std::min( it->second.first, aCopper );
3358 it->second.second = std::max( it->second.second, aCopper );
3374 for(
const BLOCK_BASE* connItemBlock : connWalker )
3376 if( connItemBlock->GetBlockType() != 0x05 )
3387 if( copper < 0 || copper >= totalCu )
3392 for(
const BLOCK_BASE* segBlock : segWalker )
3394 switch( segBlock->GetBlockType() )
3401 record( seg.m_StartX, seg.m_StartY, copper );
3402 record( seg.m_EndX, seg.m_EndY, copper );
3409 record( arc.m_StartX, arc.m_StartY, copper );
3410 record( arc.m_EndX, arc.m_EndY, copper );
3435 std::unique_ptr<PCB_VIA>
via = std::make_unique<PCB_VIA>( &
m_board );
3436 via->SetPosition(
scale( viaPos ) );
3437 via->SetNetCode( aNetCode );
3453 const int totalCu =
m_board.GetCopperLayerCount();
3455 std::optional<std::pair<int, int>> span;
3459 span = cacheIt->second;
3463 bool resolved =
false;
3464 span =
resolveViaSpan( *viaPadstack, viaPos, totalCu, resolved );
3476 const bool touchesOuter = ( span->first == 0 ) || ( span->second == totalCu - 1 );
3493 viaDrill = viaWidth / 2;
3494 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3495 wxLogTrace(
traceAllegroBuilder,
"Via at (%d, %d): no drill in padstack '%s' key %#010x, using fallback %d",
3501 const wxString& padstackName =
m_brdDb.GetString( viaPadstack->
m_PadStr );
3503 "Via at (%d, %d) in padstack '%s' key %#010x has no valid pad component, using drill-based "
3504 "fallback (%d * 2)",
3506 viaWidth = viaDrill * 2;
3509 via->SetWidth(
F_Cu, viaWidth );
3510 via->SetDrill( viaDrill );
3520 std::vector<BOARD_ITEM*> newItems;
3525 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3537 const int netCode = netIt->second->GetNetCode();
3542 [
this]( uint8_t aType,
const BLOCK_BASE& aBlock )
3551 for(
const BLOCK_BASE* connItemBlock : connWalker )
3553 const uint8_t connType = connItemBlock->GetBlockType();
3557 std::vector<std::unique_ptr<BOARD_ITEM>> newItemList;
3565 newItemList =
buildTrack( trackData, netCode );
3571 newItemList.push_back(
buildVia( viaData, netCode ) );
3601 for( std::unique_ptr<BOARD_ITEM>& newItem : newItemList )
3603 newItems.push_back( newItem.get() );
3610 m_board.FinalizeBulkAdd( newItems );
3614 wxLogTrace(
traceAllegroBuilder,
"Finished creating %zu track/via items", newItems.size() );
3626 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
3632 switch( block->GetBlockType() )
3643 newItems.push_back( std::move( rectShape ) );
3656 for(
auto& shapeItem : shapeItems )
3657 newItems.push_back( std::move( shapeItem ) );
3662 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3672 for(
const BLOCK_BASE* block : outline2Walker )
3676 switch( block->GetBlockType() )
3686 newItems.push_back( std::move( rectShape ) );
3697 newItems.push_back( std::move( rectShape ) );
3709 for(
auto& shapeItem : shapeItems )
3710 newItems.push_back( std::move( shapeItem ) );
3715 wxLogTrace(
traceAllegroBuilder,
" Unhandled block type in outline walker: %#04x", block->GetBlockType() );
3733 std::vector<std::unique_ptr<PCB_SHAPE>> graphicItems =
buildShapes( graphicContainer,
m_board );
3735 for(
auto& item : graphicItems )
3736 newItems.push_back( std::move( item ) );
3741 std::vector<BOARD_ITEM*> addedItems;
3742 for( std::unique_ptr<BOARD_ITEM>& item : newItems )
3744 addedItems.push_back( item.get() );
3748 m_board.FinalizeBulkAdd( addedItems );
3759 return cacheIt->second;
3762 uint32_t currentKey = aStartKey;
3765 static constexpr int MAX_CHAIN_LENGTH = 50000;
3768 while( currentKey != 0 && visited < MAX_CHAIN_LENGTH )
3789 outline.
Append( shapeArc );
3793 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3800 EDA_ANGLE arcAngle = endAngle - startAngle;
3802 if( clockwise && arcAngle <
ANGLE_0 )
3805 if( !clockwise && arcAngle >
ANGLE_0 )
3812 outline.
Append( shapeArc );
3815 currentKey = arc.m_Next;
3830 currentKey = seg.m_Next;
3849 VECTOR2I topRight{ botRight.x, topLeft.
y };
3850 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3852 outline.
Append( topLeft );
3853 outline.
Append( topRight );
3854 outline.
Append( botRight );
3855 outline.
Append( botLeft );
3858 outline.
Rotate( angle, topLeft );
3870 VECTOR2I topRight{ botRight.x, topLeft.
y };
3871 VECTOR2I botLeft{ topLeft.
x, botRight.y };
3873 outline.
Append( topLeft );
3874 outline.
Append( topRight );
3875 outline.
Append( botRight );
3876 outline.
Append( botLeft );
3879 outline.
Rotate( angle, topLeft );
3890 for(
const BLOCK_BASE* segBlock : segWalker )
3892 switch( segBlock->GetBlockType() )
3904 outline.
Append( shapeArc );
3908 bool clockwise = ( arc.m_SubType & 0x40 ) != 0;
3915 EDA_ANGLE arcAngle = endAngle - startAngle;
3917 if( clockwise && arcAngle <
ANGLE_0 )
3920 if( !clockwise && arcAngle >
ANGLE_0 )
3927 outline.
Append( shapeArc );
3948 segBlock->GetBlockType() );
3974 while( holeKey != 0 )
3988 polySet.
AddHole( holeOutline );
3991 holeKey = keepout.m_Next;
4009 chain.SetClosed(
true );
4019 chain.SetClosed(
true );
4029 chain.SetClosed(
true );
4049 const std::vector<const BLOCK_BASE*>& aRelatedBlocks,
4082 wxLogTrace(
traceAllegroBuilder,
" Skipping shape on layer %#02x:%#02x - unmapped copper layer",
4091 wxLogTrace(
traceAllegroBuilder,
" Skipping zone with type %#04x, key %#010x - failed to build outline",
4096 auto zone = std::make_unique<ZONE>( &
m_board );
4101 zone->SetLayer( layer );
4114 zone->SetIsRuleArea(
true );
4115 zone->SetLayerSet( layerSet );
4116 zone->SetDoNotAllowTracks( isRouteKeepout );
4117 zone->SetDoNotAllowVias( isViaKeepout );
4118 zone->SetDoNotAllowZoneFills( isRouteKeepout || isViaKeepout );
4119 zone->SetDoNotAllowPads(
false );
4120 zone->SetDoNotAllowFootprints( isPackageKeepout );
4126 zone->SetZoneName(
"Route Keepin" );
4127 else if( isPackageKeepin )
4128 zone->SetZoneName(
"Package Keepin" );
4133 for(
const BLOCK_BASE* block : aRelatedBlocks )
4138 switch( block->GetBlockType() )
4142 const auto it =
m_netCache.find( block->GetKey() );
4147 aBoundaryBlock.
GetKey(), it->second->GetNetname(), it->second->GetNetCode() );
4149 netCode = it->second->GetNetCode();
4153 m_reporter.Report( wxString::Format(
"Could not find net key %#010x in cache for BOUNDARY %#010x",
4154 block->GetKey(), aBoundaryBlock.
GetKey() ),
4164 combinedFill.
Append( fillPolySet );
4174 zone->SetNetCode( netCode );
4180 if( isCopperZone && !combinedFill.
IsEmpty() )
4194 zone->SetIsFilled(
true );
4195 zone->SetNeedRefill(
false );
4208 std::vector<const BLOCK_BASE*> ret;
4221 if( !ptrArray || ptrArray->
m_Count == 0 )
4224 const size_t count = std::min( std::min( ptrArray->
m_Count, ptrArray->
m_Capacity ), 100u );
4225 ret.resize( count );
4227 for(
size_t i = 0; i < count; i++ )
4248 if( strWrapper.GetGroupPtr() != 0 )
4256 text->GetPosition().x,
text->GetPosition().y );
4266template <std::derived_from<BOARD_ITEM> T>
4269 std::vector<BOARD_ITEM*> rawPointers;
4270 rawPointers.reserve( aItems.size() );
4272 for( std::unique_ptr<T>& item : aItems )
4274 rawPointers.push_back( item.get() );
4286 std::vector<std::unique_ptr<ZONE>> newZones;
4287 std::vector<std::unique_ptr<ZONE>> keepoutZones;
4297 std::unique_ptr<ZONE> zone;
4300 switch( block->GetBlockType() )
4309 zone =
buildZone( *block, {}, zoneFillHandler );
4320 zone =
buildZone( *block, {}, zoneFillHandler );
4332 layerInfo = shapeData.
m_Layer;
4337 wxLogTrace(
traceAllegroBuilder,
"Unhandled block type in zone shape walker: %#04x, key: %#010x",
4338 block->GetBlockType(), block->GetKey() );
4345 wxLogTrace(
traceAllegroBuilder,
" Zone %#010x net=%d layer=%s class=%#04x:%#04x", block->GetKey(),
4346 zone->GetNetCode(),
m_board.GetLayerName( zone->GetFirstLayer() ), layerInfo.m_Class,
4347 layerInfo.m_Subclass );
4349 newZones.push_back( std::move( zone ) );
4356 for(
const BLOCK_BASE* block : keepoutWalker )
4358 std::unique_ptr<ZONE> zone;
4360 switch( block->GetBlockType() )
4372 zone =
buildZone( *block, {}, zoneFillHandler );
4385 zone =
buildZone( *block, {}, zoneFillHandler );
4394 newZones.push_back( std::move( zone ) );
4401 int originalCount = newZones.size();
4410 int mergedCount = mergedZones.size();
4412 int keepoutCount = 0;
4413 int boundaryCount = 0;
4415 for(
const std::unique_ptr<ZONE>& zone : mergedZones )
4417 if( zone->GetIsRuleArea() )
4425 wxLogTrace(
traceAllegroBuilder,
"Created %d zone outlines and %d keepout areas (%d merged away), ", boundaryCount,
4426 keepoutCount, originalCount - mergedCount );
4443 const wxString& tableName =
m_brdDb.GetString( tableData.m_StringPtr );
4445 std::vector<std::unique_ptr<BOARD_ITEM>> newItems;
4449 for(
const BLOCK_BASE* keyTable : keyTableWalker )
4451 wxLogTrace(
traceAllegroBuilder,
" Table '%s' (key %#010x, table block key %#010x)", tableName,
4452 tableData.m_Key, tableData.m_Ptr1 );
4456 wxLogTrace(
traceAllegroBuilder,
" Key table pointer %#010x is invalid", tableData.m_Ptr1 );
4460 switch( keyTable->GetBlockType() )
4466 uint32_t count = std::min( ptrArray.
m_Count,
static_cast<uint32_t
>( ptrArray.
m_Ptrs.size() ) );
4468 wxLogTrace(
traceAllegroBuilder,
" Pointer array with %zu entries",
static_cast<size_t>( count ) );
4470 for( uint32_t ptrIndex = 0; ptrIndex < count; ptrIndex++ )
4472 uint32_t ptrKey = ptrArray.
m_Ptrs[ptrIndex];
4487 newItems.push_back( std::move( newItem ) );
4504 keyTable->GetBlockType() );
4510 if( newItems.size() > 0 )
4512 wxLogTrace(
traceAllegroBuilder,
" Creating group '%s' with %zu items", tableName, newItems.size() );
4514 std::unique_ptr<PCB_GROUP>
group = std::make_unique<PCB_GROUP>( &
m_board );
4515 group->SetName( tableName );
4517 for(
const auto& item : newItems )
4518 group->AddItem( item.get() );
4520 newItems.push_back( std::move(
group ) );
4543 int copperShapeCount = 0;
4544 int teardropCount = 0;
4559 const bool isDynCopperShape = ( fill.shape->m_Unknown2.value_or( 0 ) & 0x1000 ) != 0;
4561 if( isDynCopperShape )
4563 auto zone = std::make_unique<ZONE>( &
m_board );
4566 zone->SetLayer( fill.layer );
4567 zone->SetNetCode( fill.netCode );
4568 zone->SetLocalClearance( 0 );
4574 zone->AddPolygon(
chain );
4576 zone->SetFilledPolysList( fill.layer, fractured );
4577 zone->SetIsFilled(
true );
4578 zone->SetNeedRefill(
false );
4579 zone->CalculateFilledArea();
4587 shape->SetPolyShape( fractured );
4588 shape->SetFilled(
true );
4589 shape->SetLayer( fill.layer );
4590 shape->SetNetCode( fill.netCode );
4599 wxLogTrace(
traceAllegroPerf, wxT(
" applyZoneFills unmatched loop: %.3f ms (%d shapes, %d teardrops)" ),
4600 fillTimer.
msecs(
true ), copperShapeCount, teardropCount );
4606 std::unordered_map<int, std::vector<ZONE*>> teardropsByNet;
4610 if( zone->IsTeardropArea() )
4611 teardropsByNet[zone->GetNetCode()].push_back( zone );
4614 if( teardropsByNet.empty() )
4622 for(
PAD*
pad : fp->Pads() )
4624 auto it = teardropsByNet.find(
pad->GetNetCode() );
4626 if( it == teardropsByNet.end() )
4629 for(
ZONE* tdZone : it->second )
4636 pad->SetTeardropsEnabled(
true );
4650 auto it = teardropsByNet.find(
via->GetNetCode() );
4652 if( it == teardropsByNet.end() )
4655 for(
ZONE* tdZone : it->second )
4662 via->SetTeardropsEnabled(
true );
4669 wxLogTrace(
traceAllegroBuilder,
"Enabled teardrops on %d pads and %d vias", padCount, viaCount );
4677 static_cast<int>(
m_brdDb.m_FmtVer ),
4680 m_brdDb.m_Header->m_AllegroVersion.data() );
4753 std::vector<BOARD_ITEM*> bulkAddedItems;
4755 THROTTLE refreshThrottle( std::chrono::milliseconds( 100 ) );
4762 [
this, &fpBlock]( uint8_t aType,
const BLOCK_BASE& )
4764 m_reporter.Report( wxString::Format(
"Unexpected object of type %#04x found in footprint %#010x",
4765 aType, fpBlock.m_Key ),
4775 bulkAddedItems.push_back( fp.get() );
4780 m_reporter.Report( wxString::Format(
"Failed to construct footprint for 0x2D key %#010x", inst.m_Key ),
4789 wxLogTrace(
traceAllegroPerf, wxT(
" convertFootprints (%zu footprints): %.3f ms" ),
4790 bulkAddedItems.size(), buildTimer.
msecs(
true ) );
4792 if( !bulkAddedItems.empty() )
4793 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