Fixed the edge tabs overhang

This commit is contained in:
Finn Tews
2026-05-08 21:09:06 +02:00
parent ae2e631cc7
commit feac4235b2
10 changed files with 393 additions and 36 deletions

View File

@@ -23,6 +23,35 @@ export function getLastBusbarGeometries() {
return lastComputedGeometries;
}
let _orderUpdateCallback = null;
export function setOrderUpdateCallback(fn) {
_orderUpdateCallback = fn;
}
let lastPreviewState = null;
export function refreshOrderFromLastState() {
if (!_orderUpdateCallback || !lastPreviewState) return;
const { positions, cellSize, spacing, seriesCount } = lastPreviewState;
const cellRadius = cellSize / 2;
const busbarsNeeded = seriesCount + 1;
const busbarSheets = busbarStore.list.map(bb => {
if (!bb.cellIndices || bb.cellIndices.length === 0) {
return { name: bb.name, w: 0, h: 0, empty: true };
}
const pts = bb.cellIndices.map(i => positions[i]).filter(Boolean);
if (pts.length === 0) return { name: bb.name, w: 0, h: 0, empty: true };
const minX = Math.min(...pts.map(p => p[0])) - cellRadius - spacing;
const maxX = Math.max(...pts.map(p => p[0])) + cellRadius + spacing;
const minY = Math.min(...pts.map(p => p[1])) - cellRadius - spacing;
const maxY = Math.max(...pts.map(p => p[1])) + cellRadius + spacing;
return { name: bb.name, w: maxX - minX, h: maxY - minY, empty: false };
});
_orderUpdateCallback({ busbarSheets, busbarsNeeded });
}
function getEdgeTabCenters(positions, cellRadius, spacing, layoutType) {
if (!Array.isArray(positions) || positions.length < 2) {
return { top: [], bottom: [] };
@@ -218,12 +247,7 @@ function attachEdgeTabsToNearestBusbars(busbars, geometries, positions, options)
const anchorPoint = best.anchor.slice();
const edgePoint = [best.tab.x, best.tab.y];
const innerPoint = [best.tab.x, best.tab.y + inwardDirection * overlapLength];
const busbar = busbars[best.busbarIndex];
const overlapOutward = Number(busbar.overlapSize) > 0 ? Number(busbar.overlapSize) : 0;
const outerPoint = overlapOutward > 0
? [best.tab.x, best.tab.y - inwardDirection * overlapOutward]
: null;
const outerPoint = [best.tab.x, best.tab.y - inwardDirection * overlapLength];
best.geometry.extraPads = Array.isArray(best.geometry.extraPads)
? best.geometry.extraPads
@@ -243,13 +267,11 @@ function attachEdgeTabsToNearestBusbars(busbars, geometries, positions, options)
pos: innerPoint,
radius: connectorRadius,
});
if (outerPoint) {
best.geometry.extraPads.push({
key: `bms_tab_outer_${tabOverlapSide}_${best.tabKey}`,
pos: outerPoint,
radius: connectorRadius,
});
}
best.geometry.extraPads.push({
key: `bms_tab_outer_${tabOverlapSide}_${best.tabKey}`,
pos: outerPoint,
radius: connectorRadius,
});
best.geometry.extraSegments = Array.isArray(best.geometry.extraSegments)
? best.geometry.extraSegments
: [];
@@ -267,15 +289,13 @@ function attachEdgeTabsToNearestBusbars(busbars, geometries, positions, options)
toKey: `bms_tab_inner_${tabOverlapSide}_${best.tabKey}`,
radius: connectorRadius,
});
if (outerPoint) {
best.geometry.extraSegments.push({
from: edgePoint,
to: outerPoint,
fromKey: `bms_tab_edge_${tabOverlapSide}_${best.tabKey}`,
toKey: `bms_tab_outer_${tabOverlapSide}_${best.tabKey}`,
radius: connectorRadius,
});
}
best.geometry.extraSegments.push({
from: edgePoint,
to: outerPoint,
fromKey: `bms_tab_edge_${tabOverlapSide}_${best.tabKey}`,
toKey: `bms_tab_outer_${tabOverlapSide}_${best.tabKey}`,
radius: connectorRadius,
});
}
}
@@ -484,7 +504,7 @@ export function updatePreview(resetView = false) {
enabled: document.getElementById('bmsHolesType')?.value === 'tabs',
cellRadius,
spacing,
tabWidth: parseFloat(document.getElementById('height')?.value) || 10.0,
tabWidth: (parseFloat(document.getElementById('tabWidth')?.value) || 4.0) - 1,
tabOverlapSide: document.getElementById('tabOverlapSide')?.value || 'off',
overlapLength: parseFloat(document.getElementById('height')?.value) || 10.0,
layoutType,
@@ -508,7 +528,11 @@ export function updatePreview(resetView = false) {
const actualHeight = maxY - minY + cellSize + spacing * 2;
if (positions.length >= 2) {
stats.textContent = `${positions.length} cells • ${actualWidth.toFixed(0)}×${actualHeight.toFixed(0)} mm`;
const areaCm2 = (actualWidth * actualHeight / 100).toFixed(0);
stats.textContent = `${positions.length} cells • ${actualWidth.toFixed(0)}×${actualHeight.toFixed(0)} mm • ${areaCm2} cm²`;
const s = Math.max(1, Math.round(parseFloat(document.getElementById('series')?.value) || 1));
lastPreviewState = { positions, cellSize, spacing, seriesCount: s };
refreshOrderFromLastState();
}
} catch (error) {
console.error('Preview error:', error);
@@ -732,7 +756,7 @@ export async function generateLayout() {
}
}
const tabWidth = parseFloat(document.getElementById('height').value) || 10.0;
const edgeCutWidth = parseFloat(document.getElementById('tabWidth')?.value) || 4.0;
const tabLength = parseFloat(document.getElementById('tabLength')?.value) || 10.0;
const tabOverlapSide = document.getElementById('tabOverlapSide')?.value || 'off';
@@ -740,7 +764,7 @@ export async function generateLayout() {
cellSize, spacing, height, terminalDiameter, terminalDepth,
coverThickness, roundedCorners, bmsHoles, ledgeWidth,
filletBms, circleHoleOffset, useTabs, useFullCircles, bmsHoleDiameter,
tabWidth, tabLength, tabDepth: 1.0, tabOverlapSide, layoutType,
tabWidth: edgeCutWidth, tabLength, tabDepth: 1.0, tabOverlapSide, layoutType,
};
const holderShape = create3DModel(positions, config);
@@ -778,7 +802,7 @@ export async function generateLayout() {
enabled: bmsHolesType === 'tabs',
cellRadius,
spacing,
tabWidth,
tabWidth: edgeCutWidth - 1,
tabOverlapSide,
overlapLength: height,
layoutType,