Optimización de corte (nesting)
Tutorial paso a paso del módulo de nesting de Despiece: el
solver que empaqueta tus piezas en tableros stock minimizando
desperdicio, con ciclo de tiempo estimado, secuencia de corte
tipo TSP y exports listos para la sierra (PDF), la CNC (DXF),
etiquetas por tablero y piezas 2D para outsource. La
experiencia está enmarcada como propuesta de taller (no
optimizador industrial) y suma un flujo por módulo para
mantener el orden de armado a través de los tableros. El modelo
de ejemplo es CocinaV9.despiece.
packNestMulti) elige las mejores
placas por grupo de espesor, y un pipeline post-proceso
calcula secuencia de corte (TSP 2-opt), ciclo de tiempo
calibrable y exports. Atajo: N para abrir/cerrar el
panel.
Novedades 2026-08 (vs v1 del tutorial)
| Feature | Dónde |
|---|---|
| Diagrama cut-man (cut #s + leyenda + labels) | Workbench + PDF nest |
| Optimizar por módulo (A1 flujo) | Setup ▸ Optimizar para |
| Tablero auto (phantom) + banner colapsable | Setup + banner sobre el workbench |
| Compra sugerida CSV | Toolbar ▸ Compra sugerida |
| Guardar phantom → stock (1-click) | Banner expandido |
| Propuesta de taller (badge + chips de yield) | Toolbar del workbench |
| Etiquetas por tablero (≥2 tableros prompt) | Workbench ▸ Etiquetas |
| Piezas 2D (.zip DXF) por pieza neta | Exportar ▸ Piezas 2D (no desde nest) |
01 Cargar el modelo y abrir el panel
Al importar el STEP/IGES/BREP/glTF/GLB, la sidebar izquierda muestra el
árbol jerárquico. Para arrancar el corte el atajo es
N, que abre el panel modal full-screen
(nest-root) en modo Setup.
La cámara vuelve a vista isométrica con Home; el zoom encaja con F.
02 Setup: stock + sierra
El Setup tiene dos columnas. La columna izquierda carga el stock del taller y la derecha opera la sierra y los knobs del solver:
- Tableros stock — presets del taller (Melamina 18 / 15 / MDF, OSB, Fenólico, 1830×2750 / 5600, etc.) + retazos entre obras. Activá los que querés usar; el solver solo trabaja con los activados y los filtra por espesor / material. Si no cargás nada, el solver genera tableros auto (phantom) igual (ver paso 9).
- Sierra — knobs operator-facing:
kerf(mm, 0–10, step 0.5; default 3 mm).Recorte de fábrica=borderMargin(mm, 0–50; default 0).Permitir rotación 90°— si la pieza admite girar (no respeta veta).1ª pasada— H o V; sesgo leve en el ordering del solucionador.Optimizar para— Material / Tiempo / Mixto / Por módulo (ver paso 7).
- Avanzado (solver) — acordeón colapsable con
algoritmo(auto / guillotine / maxrects),restarts(1–20, default 5),time budget(1–30 s, default 5),seed(0 = random).
treePath o tenés un solo
módulo, la cola de módulos aparece vacía — Despiece cae
al comportamiento clásico (optimizar para material/tiempo) y
la fila Sin módulo se ignora.
El botón Calcular dispara packNestMulti y, cuando
termina, transiciona al modo Workbench.
03 Calcular y entrar al workbench (propuesta de taller)
Tras Calcular, el panel pasa al modo Workbench
(.nwb-workbench). La toolbar lleva ahora un
badge Propuesta de taller como recordatorio
explícito: lo que ves es una propuesta revisable, no un
optimizador industrial — podés mover piezas con drag, sacarlas
a sin colocar o recalcular.
El stage es un <canvas> que renderiza cada
tablero en milímetros con relación de aspecto real. Las piezas se
colorean por espesor / material; las rayas diagonales marcan veta.
Las bandas perimetrales marcan los cantos (rojo 0,45 mm, azul 2
mm, custom) y debajo de cada tablero va una leyenda con esos
mismos valores.
Al terminar el cálculo, sale un toast Propuesta lista · mirá % desperdicio y piezas sin colocar.
04 Anatomía del diagrama cut-man
#N con el número de secuencia de corte y leyenda 0,45 / 2 mm en la esquina inferior derecha del tablero.
Cada rectángulo dentro del tablero codifica la misma info que
antes, pero el renderizador cut-man agrega tres elementos
nuevos (src/nesting/render-cuts.ts,
render-edge-legend.ts, render-labels.ts):
| Visual | Significado |
|---|---|
| Espesor 18 mm (melamina MDP por defecto). | |
| Espesor 15 mm (fondo / tapa de cajón). | |
| Espesor 9 mm (MDF crudo / fondo económico). | |
| rayas a 45° | respectsGrain: 'h' | 'v' — la pieza no rota; bloquea reordenamientos. |
| bandas rojas / azules | Cantos en cada lado (rojo 0,45 mm · azul 2 mm · custom). |
| borde discontinuo verde | Retazo útil: puede volver al inventario como offcut. |
badges #N | Secuencia de corte del paso N — mismo orden que la tabla del panel derecho. |
leyenda 0,45 mm / 2 mm | Esquina inferior derecha del tablero, swatches de las bandas. |
Click en un rectángulo lo selecciona en el rail izquierdo y
dispara setNestHighlightedCutIndex para iluminar el
paso de secuencia correspondiente en el panel derecho.
renderBoard con
showCutNumbers: true y showEdgeLegend: true,
así el diagrama que ves en pantalla es idéntico al que mandás
al taller. Los labels tienen outline oscuro
(strokeText con rgba(14,39,64,0.85))
para que se lean incluso sobre el ámbar saturado de MDP.
05 Algoritmo: guillotine + maxrects + multi-restart
El solver tiene tres modos
(src/nesting/types.ts:NestStrategyChoice):
| Modo | Algoritmo | Cuándo |
|---|---|---|
| auto (default) | corre 5 restarts con estrategias distintas + shuffle seeded. Conserva el mejor. | Taller genérico / primera pasada. Recomendado. |
| maxrects | packMaxRects — heurística de máximo rectángulo libre (Best Short Side Fit). | Cuando querés minimizar retazos rectangulares grandes (CNC). |
| guillotine | packGuillotine — cortes válidos para sierra escuadradora (cada corte va de borde a borde). | Sierra de banco / escuadradora (el más rápido). |
En modo auto, packNestMulti
(src/nesting/multi-restart.ts) itera entre 5 sort
strategies (byMaxSide, byArea,
byPerimeter, byHeight,
byAspectRatio) con un shuffle seeded (mulberry32).
El criterio del mejor resultado depende ahora de
Optimizar para:
- Material: lexicográfico — menos tableros primero, después menor waste%.
- Tiempo: menor cycle time total (sumando setup + plunge + rapid + cut por tablero, calibrado por overhead).
- Mixto: blend de waste% y cycle time con
optimizeWeight(0–1). - Por módulo: menor flow dispersion — sumatoria de cuántos tableros distintos toca cada módulo (ver paso 7).
El restarts (1–20, default 5) sube la chance de encontrar
un layout mejor; el timeBudgetMs (1000–30000, default
5000) corta el loop aunque queden restarts pendientes. Seed
0 = random; cualquier otro valor fija la corrida para
reproducirla.
// Opciones que ve la UI (src/nesting/types.ts) DEFAULT_NEST_OPTIONS = { kerf: 3, // mm de disco borderMargin: 0, // recorte de fábrica allowRotate: true, strategy: 'auto', restarts: 5, timeBudgetMs: 5000, seed: 0, firstCut: 'v', optimize: 'material', optimizeWeight: 0.5, cutSequence: 'guillotine-naive', }
06 Cycle-time y secuencia de corte (TSP)
Una vez que el solver devuelve placements, un pipeline post-proceso calcula:
- Cuts: por cada tablero, el código genera una lista de
CutStep(H o V + posición + longitud). Los cortes son los bordes internos del layout. - Cut sequence: el algoritmo elegido ordena los cortes.
Tres opciones
(
src/nesting/cut-sequence-tsp.ts:CutSequenceAlgorithm):guillotine-naive— sort por dirección (V primero) y luego por posición. Back-compat.nearest-neighbor— greedy O(n²) partiendo de (0,0). Reduce aire vs guillotine-naive.tsp-2opt— nearest-neighbor + swaps por pares que reduzcan path. El que mejor resultado da.
- Cycle time
(
src/nesting/cycle-time.ts): por corte,cut_time = cutLength / (feedRate × feedRateScale), másrapid_time = airBeforeMm / rapidFeed, másplungeen el primer corte,toolchangepor cambio de herramienta (CNC),flipheurístico (CNC, cuando se cruza el eje Z),setuppor tablero yboard_chgentre tableros. Calibración final:final_time = raw × (1 + overheadPct / 100), ylabor_cost = (final / 3600) × hourlyRate.
El cycle time total ajustado por multiplicador de proyecto vive
en result.totalTimeSec (top-level del
NestResult) y se muestra en el cuts panel derecho.
settings.projectMultiplier (clamp 1–99). Útil
para cotizar un juego de cocina × 2 unidades — entrás dos veces
la misma cantidad de piezas y el time final sale × 2 sin tocar
el solver.
// Spec: docs/superpowers/specs/2026-07-18-cut-time-estimation.md cut_time = cutLength / (feedRate × feedRateScale) rapid_time = airBeforeMm / rapidFeed plunge = first cut only // panel saw toolchange = per tool boundary // CNC flip = heuristic (Z crossing) // CNC setup = setupTimeSec per board board_chg = boardChangeTimeSec per board // after first final_time = raw × (1 + overheadPct / 100) labor_cost = (final_time / 3600) × hourlyRate
07 Optimizar por módulo (flujo A1)
Cuando elegís Optimizar para: Por módulo, el solver
agrupa las piezas por módulo de armado (parent directo
del leaf en el treePath) y optimiza para que cada
módulo quede lo más concentrado posible — menos tableros
distintos por módulo, mejor secuencia para armar en taller.
El setup muestra una cola de módulos debajo del listado
de stock:
- Reordenar: ↑ / ↓ en cada fila, o drag & drop
para mover bloques enteros. El orden define el pack priority
(
moduleRank0 = primero). - Excluir: × quita el módulo del nest; sus piezas caen a Sin módulo (rank alto).
- Re-agregar: + en la zona Excluidos lo vuelve a meter al final de la cola.
- Sin módulo (bucket sintético): piezas sin
treePatho que no caen bajo ningún módulo. Rank alto por default; podés ordenarlo o quitarlo con × (sus piezas quedan sin colocar).
treePath de cada
BuiltPart
(src/nesting/module-resolve.ts:modulesFromTreePaths).
Si el modelo es plano (sin jerarquía) o no tiene módulos
reconocibles, la cola aparece vacía y el sistema cae al
comportamiento de Material / Tiempo sin penalizarte.
Flow chip en la toolbar
optimize = by_module, el flow chip flujo 3,3 · 11 mod aparece debajo de los chips de yield. Hover lista cada módulo con su span (T1, T2, T4…).
Tras correr con optimize = by_module, la toolbar
muestra un chip extra: flujo X.X · N mod (avg de tableros
distintos por módulo). Hover sobre el chip lista cada módulo con
su span:
# Tooltip del flow chip (nesting.workbench.flow_line) Bajo 01 → T1,T3 (span 2) Alacena → T2 (span 1) Mueble heladera → T4,T5 (span 2) …
moduleStats se preservan incluso cuando
recalculás con optimize = material (commit
dc5c923), así que el chip sigue mostrándose como
referencia histórica.
08 Edit SOTA: drag, snap, rotate
El workbench expone un set de ediciones manuales SOTA (spec §Edit SOTA):
- Drag — mover una pieza. Snap a bordes de pieza, kerf y outline.
userMoved: truetras commit. - Rotate R — gira la pieza seleccionada 90°. Si la pieza respeta veta, la rotación queda bloqueada.
- Cross-board — arrastrar una pieza entre dos tableros del mismo espesor/material. Si no entra, el sistema lo rechaza con un transient.
- Unscheduled — quitar piezas del layout va al rail Sin colocar; desde ahí se pueden volver a poner en otro tablero.
- Recompute — cada commit dispara
recomputeBoardAfterEditque recalculausedArea,cutsy stats delresult. - Doble click en lista — mueve la pieza seleccionada a Sin colocar.
El undo del workbench es local (no toca History 3D); se compone con el history general sólo si lo engancha el panel.
09 Tablero auto (phantom) + compra sugerida
Cuando el modelo tiene espesores / materiales que no
matchean con el stock cargado, el solver ya no tira error:
genera tableros auto (phantom) del tamaño mínimo
necesario para las piezas huérfanas
(src/nesting/material-pack.ts:generatePhantomStock).
Los phantoms vienen con phantom: true y un badge
· phantom en la cabecera del tablero en el canvas.
Nunca se persisten en despiece.stockboards
ni en despiece-stock.
Banner colapsable
- Cada fila muestra material · dimensiones · cantidad.
- Guardar en mis tableros → abre el material picker,
promueve el phantom a
StockBoardreal (promote-phantom.ts) y lo suma al stock del nest. - También al inventario del taller — si está tildado,
replica en
despiece-stock(IDB v2). - Hint: "Cargá un tablero real o un preset para mejorar el aprovechamiento".
Compra sugerida (CSV)
compra-sugerida-{modelo}.csv.
Si el solver usó phantoms, en la toolbar aparece el botón
Compra sugerida (exportNestSuggestedBoards).
Click genera y descarga compra-sugerida-{modelo}.csv:
# compra-sugerida-{modelo}.csv (UTF-8 BOM + CRLF) material,espesor_mm,largo_mm,ancho_mm,cantidad,origen Sin material,18,2750,1830,5,tablero_auto MDF crudo,15,1830,600,2,tablero_auto
Una fila por phantom único (dedupeado por material × espesor × dims × cantidad).
10 Exportar: PDF · CSV · DXF · Etiquetas · Piezas 2D
La toolbar del workbench tiene cinco botones de export, todos sobre el resultado actual (respetan la selección del diagrama):
| Botón | Salida | Spec / módulo |
|---|---|---|
| Plan completo en PDF (diagrama grande por tablero + tabla de secuencia de cortes + cantos por pieza). | src/export-nest-pdf/, src/ui/nesting-export.ts:exportNestPdf | |
| CSV | Listado pieza-a-pieza: coords, rotada, canto, material, tablero origen. Listo para abrir en Excel/Opticut. | src/export-nest-csv/, src/ui/nesting-export.ts:exportNestCsv |
| Compra sugerida | CSV de tableros auto generados (sólo cuando hubo phantoms). | src/export/nest-suggested-boards.ts |
| DXF (.zip) | Un .dxf por tablero, bundleados en nest-{modelo}.zip. Formato AutoCAD R14, capas BOARD, PIECE, CUT, LABEL, GRAIN. | src/export-nest-dxf/, spec 2026-07-18-export-nest-dxf.md |
| Etiquetas | PDF de etiquetas pieza-a-pieza (datos para pegarlas en el taller). | src/ui/nesting-export-labels.ts |
partsForExport() / el
result.boards actual: si moviste una pieza con drag
(paso 8), la nueva posición se exporta, no la original del solver.
Etiquetas filtradas por tablero
Cuando el resultado tiene ≥2 tableros, el botón Etiquetas muestra el inline prompt Etiquetas por tablero:
# Etiquetas por tablero Número de tablero a reimprimir (1, 2, 3, 4, 5). Vacío = todos. Actual: 1. [Vacio = todos los tableros ] [Cancelar] [Guardar]
Default vacío = exporta todas las etiquetas. Ingresás un número y
sólo se exportan las piezas de ese tablero (filtrado por
boardIndex vía
export-labels/filter.ts:filterCutLabels).
Piezas 2D (.zip DXF) — desde el menú Exportar
Las Piezas 2D viven en Exportar ▸ Piezas 2D
(no en la toolbar del nest). Es un export independiente del
cálculo de nesting — útil para mandar a un outsource / CNC
sin compartir el layout:
- Un DXF R14 neto por pieza (cantos descontados via
cutFaceDimensions). - Origen
(0, 0)— listo para cargar en cualquier CAM. - Label centrado:
nombre WxHen capaLABEL. - ZIP
piezas-2d-{modelo}.zip.
nest-{modelo}.zip, los DXF de
piezas 2D no llevan trayectorias ni G-code — son
geometría para cotización / nesting externo.
Tabla resumen del output
| ¿Qué querés? | Botón | Spec |
|---|---|---|
| Llevar el plan a la sierra | 2026-07-18-cut-time-estimation.md | |
| Abrir en OptiCut o Excel | CSV | — |
| Cargar en AutoCAD / CAM (un DXF por tablero) | DXF (.zip) | 2026-07-18-export-nest-dxf.md |
| Pegar etiquetas en las piezas físicas | Etiquetas | 39ffc31 (filtro por tablero) |
| Cotizar / mandar a hacer afuera (un DXF por pieza) | Exportar ▸ Piezas 2D | 95f4ce5 |
| Comprar los tableros auto detectados | Compra sugerida | b4d6188 |
11 Ciclar semilla R y comparar
El atajo R, mientras el panel está abierto y
no está computando, dispara triggerRegenerate
que es runCompute(true) con un nuevo seed aleatorio.
La historia de restarts vive en
result.restartsHistory y el mejor seed se persiste en
result.bestSeed (top-level del
NestResult).
Comparando corrida tras corrida se ve el efecto del shuffle: una
pieza "rara" puede bajar 2–4 % el desperdicio cuando cae en un
casillero que el baseline dejaba vacío. En modo
auto + 5 restarts, el panel normalmente te muestra
el mejor de los 5 al terminar.
restarts a 20 o
timeBudgetMs a 30 s puede duplicar el tiempo de
cálculo sin mejorar el resultado. Para CocinaV9 (40–60 piezas)
los defaults funcionan bien; subí restarts solo si tenés > 200
piezas o mezclas thicknesses.
12 Atajos de teclado
Help (botón de la topbar o ?) abre la hoja completa.
Los más usados en el flujo de nesting:
| Atajo | Acción |
|---|---|
| N | Abrir / cerrar panel de nesting (toggleNestingPanel). |
| Esc | Cerrar el panel (si no está computando). |
| R | Recalcular con semilla nueva — dentro del panel, solo si no hay computación en curso. |
| R (pieza seleccionada) | Rotar la pieza seleccionada 90° (siempre que orientationsForGrain lo permita). |
| Click + drag | Mover pieza en el workbench (snap-to-kerf). |
| Click rectángulo | Seleccionar pieza en el rail e iluminar corte en el cuts panel. |
| Doble click lista | Mover pieza seleccionada a Sin colocar. |
| F / Home | Fit / Fit + iso del viewport 3D. |
En Mac el modificador de sistema es ⌘; en otros sistemas Ctrl.
Ver también
- Tutorial · Cantos y auto-cantos
- Tutorial · Roles y auto-roles
- Spec 2026-07-10-nesting-optimizer.md — diseño v1 del solver.
- Spec 2026-07-11-nesting-v2.md — v2, multi-material / grain.
- Spec 2026-07-15-nesting-workbench-sota.md — workbench SOTA (drag, snap, edit).
- Spec 2026-07-18-cut-time-estimation.md — cycle time + TSP.
- Spec 2026-07-18-export-nest-dxf.md — export DXF (.zip).