- {/* Sidebar List (Grid Layout) */}
+ {/* Боковая панель (Сетка) */}
diff --git a/src/services/geometryGenerator.ts b/src/services/geometryGenerator.ts
index 35a4fff..14b17c9 100644
--- a/src/services/geometryGenerator.ts
+++ b/src/services/geometryGenerator.ts
@@ -83,7 +83,7 @@ const createConcaveFilletShape = (radius: number): THREE.Shape => {
return shape;
};
-// New Helper: Create Perforated Plate (Vertical Wall)
+// Вспомогательная функция: Создание перфорированной пластины (Вертикальная стенка)
const createPerforatedPlate = (
width: number,
height: number,
@@ -100,17 +100,17 @@ const createPerforatedPlate = (
shape.lineTo(0, height);
shape.lineTo(0, 0);
- // Hole Generation
+ // Генерация отверстий
if (perf && perf.enabled && width > perf.size && height > perf.size) {
const { shape: shapeType, size, gap } = perf;
const step = size + gap;
- // Margins: ensure holes don't cut into the solid edge zones
+ // Отступы: предотвращаем попадание отверстий на сплошные края
const startX = Math.max(gap, marginLeft + gap);
const startY = gap;
const endX = width - Math.max(gap, marginRight + gap);
const endY = height - gap;
- // Rows
+ // Строки
let row = 0;
for (let y = startY + size / 2; y < endY; y += (shapeType === 'triangle' || shapeType === 'honeycomb' ? step * 0.866 : step)) {
const isStaggered = (row % 2 !== 0);
@@ -120,18 +120,18 @@ const createPerforatedPlate = (
const hole = new THREE.Path();
const r = size / 2;
- // Boundary check
+ // Проверка границ
if (x - r < marginLeft || x + r > width - marginRight || y - r < 0 || y + r > height) continue;
- // Exclusion Zone Check
- // Zone active if hole X is within [start, end] AND hole Y is below yMax (if specified).
- // If y > yMax, the exclusion doesn't apply (it's above the intersecting wall).
- // Note: y is measured from bottom (0) to top (height).
- // yMax is the height of the intersecting partition.
+ // Проверка зон исключения
+ // Зона активна, если X отверстия входит в [start, end] И Y отверстия ниже yMax (если указан).
+ // Если y > yMax, исключение не применяется (отверстие выше пересекающей стенки).
+ // Примечание: y измеряется от низа (0) до верха (height).
+ // yMax - высота пересекающей перегородки.
const inExclusion = exclusions.some(zone => {
- if (x + r <= zone.start || x - r >= zone.end) return false; // X-axis check
- if (zone.yMax !== undefined && y - r > zone.yMax) return false; // Y-axis check (hole above wall)
+ if (x + r <= zone.start || x - r >= zone.end) return false; // Проверка по оси X
+ if (zone.yMax !== undefined && y - r > zone.yMax) return false; // Проверка по оси Y (отверстие выше стенки)
return true;
});
@@ -140,7 +140,7 @@ const createPerforatedPlate = (
if (shapeType === 'circle') {
hole.absarc(x, y, r, 0, Math.PI * 2, true);
} else if (shapeType === 'honeycomb') {
- // Hexagon
+ // Шестиугольник (Соты)
for (let i = 0; i < 6; i++) {
const ang = (i * 60 + 30) * Math.PI / 180;
const px = x + r * Math.cos(ang);
@@ -150,7 +150,7 @@ const createPerforatedPlate = (
}
hole.closePath();
} else if (shapeType === 'triangle') {
- // Triangle
+ // Треугольник
const ang1 = -90 * Math.PI / 180;
const ang2 = 30 * Math.PI / 180;
const ang3 = 150 * Math.PI / 180;
@@ -166,37 +166,37 @@ const createPerforatedPlate = (
}
const geo = new THREE.ExtrudeGeometry(shape, { depth: thickness, bevelEnabled: false });
- // Extruded along Z. Wall is flat on XY.
- // We want "thickness" to be Z depth.
+ // Выдавливание по Z. Стенка плоская в XY.
+ // Мы хотим, чтобы "thickness" была глубиной по Z.
return geo;
};
-// New Helper: Create Corner Profile (Extruded Vertical)
+// Вспомогательная функция: Создание профиля угла (Выдавленный вертикально)
const createCornerProfile = (radius: number, thickness: number, height: number): THREE.BufferGeometry => {
if (radius <= 0) return new THREE.BufferGeometry();
const shape = new THREE.Shape();
- // Create a Ring Segment (Hollow Corner) as a single loop.
- // Center at (0,0).
- const innerRadius = Math.max(0.01, radius - thickness); // Ensure slightly > 0 to maintain shape integrity
+ // Создаем сегмент кольца (Полый угол) как единый контур.
+ // Центр в (0,0).
+ const innerRadius = Math.max(0.01, radius - thickness); // Гарантируем чуть > 0 для целостности формы
- // 1. Start at Outer Start
+ // 1. Начало внешней дуги
shape.moveTo(radius, 0);
- // 2. Outer Arc (CCW) -> To (0, radius)
+ // 2. Внешняя дуга (против часовой стрелки) -> К (0, radius)
shape.absarc(0, 0, radius, 0, Math.PI / 2, false);
- // 3. Line to Inner End (0, innerRadius)
+ // 3. Линия к внутреннему концу (0, innerRadius)
shape.lineTo(0, innerRadius);
- // 4. Inner Arc (CW) -> To (innerRadius, 0)
+ // 4. Внутренняя дуга (по часовой стрелке) -> К (innerRadius, 0)
shape.absarc(0, 0, innerRadius, Math.PI / 2, 0, true);
- // 5. Close loop
+ // 5. Замыкаем контур
shape.lineTo(radius, 0);
- // Extrude
- // curveSegments 32 for smoothness
+ // Выдавливание
+ // curveSegments 32 для гладкости
const geo = new THREE.ExtrudeGeometry(shape, { depth: height, bevelEnabled: false, curveSegments: 32 });
return geo;
};
@@ -218,9 +218,9 @@ export const createBinGeometry = (
floorGeo.rotateX(-Math.PI / 2); // Lay flat
geometries.push(floorGeo);
- // WALLS
+ // СТЕНКИ
if (!perforation || !perforation.enabled) {
- // --- ORIGINAL LOGIC (Optimized for Solid Walls) ---
+ // --- ЛОГИКА ДЛЯ СПЛОШНЫХ СТЕН (Без перфорации) ---
const outerShape = createRoundedRectShape(width, depth, radius);
const innerRadius = Math.max(0.1, radius - thickness);
const innerWidth = width - (2 * thickness);
@@ -237,78 +237,78 @@ export const createBinGeometry = (
wallGeo.translate(0, thickness, 0);
geometries.push(wallGeo);
} else {
- // --- PERFORATED LOGIC (Split Walls) ---
+ // --- ЛОГИКА ДЛЯ ПЕРФОРИРОВАННЫХ СТЕН (Раздельные части) ---
const wallHeight = height - thickness;
- // Clamp radius to at least thickness for valid corners in this mode
+ // Ограничиваем радиус минимум толщиной стенки для корректных углов
const effRadius = Math.max(radius, thickness);
const straightW = width - 2 * effRadius;
const straightD = depth - 2 * effRadius;
- // 1. Corners (4 pcs)
+ // 1. Углы (4 шт)
if (effRadius > 0) {
const cornerGeoBase = createCornerProfile(effRadius, thickness, wallHeight);
- // 1. Stand Up: Extrusion Z -> Y. Shape moves to X(+)/Z(+).
+ // 1. Поднимаем: Выдавливание Z -> Y. Форма перемещается в X(+)/Z(+).
cornerGeoBase.rotateX(-Math.PI / 2);
- // Base Corner Shape (after rotateX) is Q4 (+X, -Z).
- // Rotation Logic: -90 degrees per Quadrant (Standard Three.js Y-Rot).
+ // Базовая форма угла (после rotateX) это Q4 (+X, -Z).
+ // Логика вращения: -90 градусов на квадрант (Стандартный Y-Rot в Three.js).
// Q4 (0) -> Q1 (-90) -> Q2 (-180/180) -> Q3 (-270/+90).
const positions = [
- // Back Right (+X, +Z). Q1.
- // Rot -90 (-PI/2).
+ // Задний Правый (+X, +Z). Q1.
+ // Поворот -90 (-PI/2).
{ x: width / 2 - effRadius, z: depth / 2 - effRadius, rot: -Math.PI / 2 },
- // Back Left (-X, +Z). Q2.
- // Rot 180 (PI).
+ // Задний Левый (-X, +Z). Q2.
+ // Поворот 180 (PI).
{ x: -(width / 2 - effRadius), z: depth / 2 - effRadius, rot: Math.PI },
- // Front Left (-X, -Z). Q3.
- // Rot 90 (PI/2). (Equivalent to -270).
+ // Передний Левый (-X, -Z). Q3.
+ // Поворот 90 (PI/2). (Эквивалентно -270).
{ x: -(width / 2 - effRadius), z: -(depth / 2 - effRadius), rot: Math.PI / 2 },
- // Front Right (+X, -Z). Q4.
- // Rot 0.
+ // Передний Правый (+X, -Z). Q4.
+ // Поворот 0.
{ x: width / 2 - effRadius, z: -(depth / 2 - effRadius), rot: 0 }
];
positions.forEach(pos => {
const corner = cornerGeoBase.clone();
corner.rotateY(pos.rot);
- corner.translate(pos.x, 0, pos.z); // Start at Y=0
- corner.translate(0, thickness, 0); // Move on top of floor
+ corner.translate(pos.x, 0, pos.z); // Старт на Y=0
+ corner.translate(0, thickness, 0); // Сдвиг на толщину дна
geometries.push(corner);
});
}
- // 2. Straight Walls (4 pcs) - Centered on edges
+ // 2. Прямые стены (4 шт) - Центрированы по краям
- // REWRITE EXCLUSION COLLECTION LOGIC TO BE WALL-SPECIFIC
+ // ЛОГИКА СБОРА ИСКЛЮЧЕНИЙ ДЛЯ СТЕН
const exclusionsBack: { start: number, end: number, yMax: number }[] = [];
const exclusionsFront: { start: number, end: number, yMax: number }[] = [];
const exclusionsLeft: { start: number, end: number, yMax: number }[] = [];
const exclusionsRight: { start: number, end: number, yMax: number }[] = [];
- // Inner Dimensions
+ // Внутренние размеры
const effectiveInnerW = width - 2 * thickness;
const effectiveInnerD = depth - 2 * thickness;
partitions.forEach(p => {
- const hEff = Math.max(0.1, p.height - thickness); // Exclude only up to partition height
- // Ensure solid strip around partition by adding padding to exclusion zone
+ const hEff = Math.max(0.1, p.height - thickness); // Исключаем только до высоты перегородки
+ // Гарантируем сплошную полосу вокруг перегородки добавлением отступа к зоне исключения
const padding = (perforation?.gap ?? 2) + 1;
if (p.axis === 'x') {
- // Runs Depth-wise (Y axis in Layout).
- // Intersects Front and Back walls.
+ // Идет по глубине (Ось Y в макете).
+ // Пересекает Переднюю и Заднюю стенки.
const partGlobalX = (-effectiveInnerW / 2) + (effectiveInnerW * p.offset);
const sW = width - 2 * effRadius;
const localXOnWall = partGlobalX + sW / 2;
- // Check intersection with active straight wall area + padding
+ // Проверка пересечения с активной зоной стены + отступ
if (localXOnWall + thickness / 2 + padding > 0 && localXOnWall - thickness / 2 - padding < sW) {
const zone = {
start: localXOnWall - thickness / 2 - padding,
@@ -316,13 +316,13 @@ export const createBinGeometry = (
yMax: hEff
};
- if ((p.max ?? 1) > 0.99) exclusionsFront.push(zone); // Near
- if ((p.min ?? 0) < 0.01) exclusionsBack.push(zone); // Far
+ if ((p.max ?? 1) > 0.99) exclusionsFront.push(zone); // Ближняя
+ if ((p.min ?? 0) < 0.01) exclusionsBack.push(zone); // Дальняя
}
} else { // p.axis === 'y'
- // Runs Width-wise (X axis in Layout).
- // Intersects Left and Right walls.
+ // Идет по ширине (Ось X в макете).
+ // Пересекает Левую и Правую стенки.
const partGlobalZ = (-effectiveInnerD / 2) + (effectiveInnerD * p.offset);
const sD = depth - 2 * effRadius;
@@ -345,21 +345,21 @@ export const createBinGeometry = (
}
});
- // Front/Back
+ // Передняя/Задняя
if (straightW > 0.1) {
- // Wall 1 (at +Z). This is "Front" (Near). Contacts p.max.
- // Uses exclusionsFront.
+ // Стенка 1 (+Z). Это "Передняя" (Ближняя). Контактирует с p.max.
+ // Использует exclusionsFront.
const wGeoFront = createPerforatedPlate(straightW, wallHeight, thickness, perforation, 0, 0, exclusionsFront);
wGeoFront.translate(-straightW / 2, 0, 0);
const w1 = wGeoFront.clone();
w1.translate(0, thickness, depth / 2 - thickness);
geometries.push(w1);
- // Wall 2 (at -Z). This is "Back" (Far). Contacts p.min.
- // Uses exclusionsBack.
- // Needs checking mapping (Rot 180).
- // p.offset increases X. Wall rotated 180 means X is inverted.
- // So we map exclusionsBack.
+ // Стенка 2 (-Z). Это "Задняя" (Дальняя). Контактирует с p.min.
+ // Использует exclusionsBack.
+ // Нужна проверка маппинга (Поворот 180).
+ // p.offset увеличивает X. Стенка повернута на 180, значит X инвертирован.
+ // Маппим exclusionsBack.
const exclusionsBackMapped = exclusionsBack.map(e => ({
start: straightW - e.end,
end: straightW - e.start,
@@ -374,27 +374,23 @@ export const createBinGeometry = (
geometries.push(w2);
}
- // Left/Right
+ // Левая/Правая
if (straightD > 0.1) {
- // Wall 3 (Right? +X).
- // Plate is 0..straightD in X, 0..wallHeight in Y. Thickness along Z.
- // We want it to be at X = width/2.
- // It needs to be rotated -PI/2 around Y to align its X-axis with World Z-axis.
- // After rotateY(-PI/2): Plate X (0..straightD) becomes World Z (0..straightD).
- // Plate Z (thickness) becomes World -X (towards Left).
- // So if we place it at X=width/2, it extrudes to width/2 - thickness. Correct for Right Wall.
+ // Стенка 3 (Правая +X).
+ // Пластина 0..straightD по X, 0..wallHeight по Y. Толщина по Z.
+ // Хотим разместить на X = width/2.
+ // Нужно повернуть -PI/2 вокруг Y чтобы выровнять ось X пластины с мировой осью Z.
const wGeoRight = createPerforatedPlate(straightD, wallHeight, thickness, perforation, 0, 0, exclusionsRight);
- wGeoRight.translate(-straightD / 2, 0, 0); // Center X of plate
+ wGeoRight.translate(-straightD / 2, 0, 0); // Центр X пластины
const w3 = wGeoRight.clone();
- w3.rotateY(-Math.PI / 2); // Rotate to align with Z-axis
- w3.translate(width / 2, thickness, 0); // Position at X=width/2
+ w3.rotateY(-Math.PI / 2); // Поворот
+ w3.translate(width / 2, thickness, 0); // Позиция на X=width/2
geometries.push(w3);
- // Wall 4 (Left? -X).
- // This wall is also rotated PI/2.
- // Plate Z (thickness) becomes World X (towards Right).
- // We want it at X=-width/2.
- // It will extrude to -width/2 + thickness. Correct for Left Wall.
+ // Стенка 4 (Левая -X).
+ // Также повернута на PI/2.
+ // Толщина по Z станем Мировой X (направо).
+ // Хотим на X=-width/2.
const exclusionsLeftMapped = exclusionsLeft.map(e => ({
start: straightD - e.end,
end: straightD - e.start,
@@ -402,10 +398,10 @@ export const createBinGeometry = (
}));
const wGeoLeft = createPerforatedPlate(straightD, wallHeight, thickness, perforation, 0, 0, exclusionsLeftMapped);
- wGeoLeft.translate(-straightD / 2, 0, 0); // Center X of plate
+ wGeoLeft.translate(-straightD / 2, 0, 0); // Центр X пластины
const w4 = wGeoLeft.clone();
w4.rotateY(Math.PI / 2);
- w4.translate(-width / 2, thickness, 0); // Position at X=-width/2
+ w4.translate(-width / 2, thickness, 0); // Позиция на X=-width/2
geometries.push(w4);
}
}
@@ -413,7 +409,7 @@ export const createBinGeometry = (
// ВНУТРЕННИЕ ПЕРЕГОРОДКИ
const innerWidth = width - (2 * thickness);
- const innerDepth = depth - (2 * thickness); // Approximate usable space logic
+ const innerDepth = depth - (2 * thickness); // Приблизительное полезное пространство
partitions.forEach(p => {
const pMin = p.min ?? 0;
@@ -424,97 +420,84 @@ export const createBinGeometry = (
const lengthRatio = pMax - pMin;
const midRatio = pMin + (lengthRatio / 2);
- // FIX: Subtract thickness because partitions sit ON TOP of the floor
+ // ИСПРАВЛЕНИЕ: Вычитаем толщину, так как перегородки стоят НА дне
const effectiveHeight = Math.max(0.1, p.height - thickness);
- // --- PERFORATED LOGIC FOR PARTITIONS ---
- // If enabled, use Plate. Else use Extrude Solid.
+ // --- ЛОГИКА ДЛЯ ПЕРФОРИРОВАННЫХ ПЕРЕГОРОДОК ---
+ // Если включено, используем Пластину. Иначе - сплошное Выдавливание.
const usePerf = perforation && perforation.enabled;
- let pX = 0, pY = 0; // Declare here for visibility in Fillets
+ let pX = 0, pY = 0; // Объявляем здесь для видимости в Скруглениях
if (usePerf) {
- // Calculate exact geometry
+ // Вычисляем точную геометрию
let pLen = 0;
if (p.axis === 'x') {
- // Axis X -> Divider runs along Y (Depth)
+ // Ось X -> Разделитель идет вдоль Y (Глубина)
pLen = lengthRatio * innerDepth;
pX = (-innerWidth / 2) + (innerWidth * p.offset);
- pY = (-innerDepth / 2) + (innerDepth * midRatio); // Center of partition
+ pY = (-innerDepth / 2) + (innerDepth * midRatio); // Центр перегородки
- // Calculate Exclusions for Internal Partition
+ // Вычисляем исключения для внутренней перегородки
const partExclusions: { start: number, end: number, yMax?: number }[] = [];
- // This partition is 'p' (Axis X, runs along Depth).
- // Intersected by partitions 'n' (Axis Y, runs along Width).
- // p global Y range: pY - pLen/2 to pY + pLen/2.
- // n global Y pos: (-innerDepth/2) + (innerDepth * n.offset).
+ // Эта перегородка 'p' (Ось X, идет по Глубине).
+ // Пересекается перегородками 'n' (Ось Y, идут по Ширине).
partitions.forEach(n => {
- if (n.axis !== 'y') return; // Only orthogonal partitions intersect
- // Check if n intersects p
- // Intersection Y location:
+ if (n.axis !== 'y') return; // Пересекаются только ортогональные перегородки
+ // Проверяем, пересекает ли n перегородку p
+ // Y-координата пересечения:
const nY = (-innerDepth / 2) + (innerDepth * n.offset);
- // Does nY (which is global Y of the intersecting partition) match p's position?
- // p is Axis X, runs along DEPTH (Global Y).
- // p is centered at pX (Width) and covers pLen in Depth (Y).
- // Wait. p (Axis X) runs along Y?
- // p.axis='x' -> "Runs along Y (Depth)". Correct.
- // So p covers Y range [pY - pLen/2, pY + pLen/2].
- // n is Axis Y, runs along X (Width).
- // n is centered at nY (Depth).
- // So intersection happens if nY is within p's Y range.
-
const pStartGlobal = pY - pLen / 2;
const pEndGlobal = pY + pLen / 2;
- // And check if n covers p's X location.
- // n runs along X from nMin to nMax.
+ // И проверяем, покрывает ли n позицию X перегородки p.
+ // n идет по X от nMin до nMax.
const nXStart = (-innerWidth / 2) + (innerWidth * (n.min ?? 0));
const nXEnd = (-innerWidth / 2) + (innerWidth * (n.max ?? 1));
const pXLoc = pX;
if (nY >= pStartGlobal && nY <= pEndGlobal && pXLoc >= nXStart && pXLoc <= nXEnd) {
- // Intersection confirmed.
- // Calculate local coord on p's plate.
- // p runs along Y. Plate local X maps to Global Y.
- // local = global - pY + pLen/2.
+ // Пересечение подтверждено.
+ // Вычисляем локальные координаты на пластине p.
+ // p идет по Y. Локальный X пластины мапится на глобальный Y.
const nHeight = Math.max(0.1, n.height - thickness);
const localX = nY - pY + pLen / 2;
partExclusions.push({ start: localX - thickness / 2, end: localX + thickness / 2, yMax: nHeight });
}
});
- // Add margins (solid ends)
+ // Добавляем отступы (сплошные концы)
const margin = thickness;
const plate = createPerforatedPlate(pLen, effectiveHeight, thickness, perforation!, margin, margin, partExclusions);
- plate.translate(-pLen / 2, 0, 0); // Center X
+ plate.translate(-pLen / 2, 0, 0); // Центр X
- // Rotate to align with Depth (along Z)
- // Plate X -> Z
+ // Поворачиваем для выравнивания по Глубине (вдоль Z)
+ // Пластина X -> Z
plate.rotateY(-Math.PI / 2);
- // Position
- // Plate is now vertical Z-aligned. Thickness along X.
+ // Позиционирование
+ // Пластина теперь вертикально по Z. Толщина по X.
plate.translate(pX + thickness / 2, thickness, pY);
geometries.push(plate);
} else {
- // Axis Y -> Divider runs along X (Width)
+ // Ось Y -> Разделитель идет вдоль X (Ширина)
pLen = lengthRatio * innerWidth;
pX = (-innerWidth / 2) + (innerWidth * midRatio);
pY = (-innerDepth / 2) + (innerDepth * p.offset);
- // Calculate Exclusions
+ // Вычисление исключений
const partExclusions: { start: number, end: number, yMax?: number }[] = [];
- // This partition is 'p' (Axis Y, runs along Width).
- // Intersected by partitions 'n' (Axis X, runs along Depth).
+ // Эта перегородка 'p' (Ось Y, идет по Ширине).
+ // Пересекается перегородками 'n' (Ось X, идут по Глубине).
partitions.forEach(n => {
if (n.axis !== 'x') return;
const nX = (-innerWidth / 2) + (innerWidth * n.offset);
- const pStartGlobal = pX - pLen / 2; // X range of p
+ const pStartGlobal = pX - pLen / 2; // Диапазон X для p
const pEndGlobal = pX + pLen / 2;
const nYStart = (-innerDepth / 2) + (innerDepth * (n.min ?? 0));
@@ -522,9 +505,8 @@ export const createBinGeometry = (
const pYLoc = pY;
if (nX >= pStartGlobal && nX <= pEndGlobal && pYLoc >= nYStart && pYLoc <= nYEnd) {
- // Intersection confirmed
- // local = global - pX + pLen/2
- const nHeight = Math.max(0.1, n.height - thickness); // INTERSECTING PARTITION HEIGHT
+ // Пересечение подтверждено
+ const nHeight = Math.max(0.1, n.height - thickness); // ВЫСОТА ПЕРЕСЕКАЮЩЕЙ ПЕРЕГОРОДКИ
const localX = nX - pX + pLen / 2;
partExclusions.push({ start: localX - thickness / 2, end: localX + thickness / 2, yMax: nHeight });
}
@@ -532,20 +514,19 @@ export const createBinGeometry = (
const margin = thickness;
const plate = createPerforatedPlate(pLen, effectiveHeight, thickness, perforation!, margin, margin, partExclusions);
- plate.translate(-pLen / 2, 0, 0); // Center X
+ plate.translate(-pLen / 2, 0, 0); // Центр X
- // Already aligned with X. Thickness along Z.
- // Z range [0, th]. We want [-th/2, th/2] relative to pY.
- // Translate Z by -th/2.
+ // Уже выровнено по X. Толщина по Z.
+ // Диапазон Z [0, th]. Мы хотим [-th/2, th/2] относительно pY.
plate.translate(0, 0, -thickness / 2);
- // Move to position
+ // Перемещение на позицию
plate.translate(pX, thickness, pY);
geometries.push(plate);
}
} else {
- // --- SOLID LOGIC ---
+ // --- ЛОГИКА ДЛЯ СПЛОШНЫХ ПЕРЕГОРОДОК ---
let pWidth = 0, pDepth = 0;
if (p.axis === 'x') {
pWidth = thickness;
@@ -566,12 +547,12 @@ export const createBinGeometry = (
geometries.push(partGeo);
}
- // Fillets Logic for partitions (Keep solid for strength/aesthetics)
+ // Логика скруглений для перегородок (Оставляем сплошными для прочности/эстетики)
if (p.rounded && radius > 1) {
const filletR = Math.min(radius, 5);
const filletShape = createConcaveFilletShape(filletR);
- // Helper to get neighbor height
+ // Помощник для получения высоты соседа
const getNeighborHeight = (pos: number) => {
if (pos < 0.001 || pos > 0.999) return height;
const neighbor = partitions.find(n => {