Sari la conținutul principal
Pe această pagină▾

Engine API

Dacă doar tai panouri, nu ai nevoie de această pagină. Optimizatorul din CutOptim face deja tot ce este descris aici. Engine API este același motor, doar fără ecran, pentru situația în care alt software are nevoie de planuri de tăiere fără ca o persoană să deschidă aplicația.

Tot ce face CutOptim în browserul tău pornește de la un singur calcul: având aceste piese și acest material de bază, care este cel mai bun mod de a le tăia? Engine API expune exact acel calcul prin internet, astfel încât un alt program să poată pune întrebarea și să primească răspunsul înapoi — fără browser, fără clicuri, fără ca nimeni să fie autentificat.

Asta este toată ideea. Nu este un optimizator nou, nu este un optimizator mai bun și nu este un plan mai mare. Este același motor, accesibil pentru software în loc de o persoană.


Este pentru mine?

Pentru marea majoritate a utilizatorilor CutOptim, răspunsul sincer este nu. Dacă ziua ta de lucru înseamnă să deschizi CutOptim, să introduci piesele și materialul de bază și să tipărești sau să exporți planul, aplicația este produsul, iar această pagină nu te privește.

Engine API este pentru o singură situație: planurile de tăiere trebuie să apară în interiorul unui software pe care îl folosești deja, fără ca nimeni să intre pe CutOptim. În practică, asta înseamnă una din două persoane:

  • Folosești deja un software în care planul de tăiere își are locul. Un ERP care ține comenzile, o aplicație de ofertare care calculează prețul lucrărilor sau software-ul propriu al unei mașini. În loc ca un operator să reintroducă aceeași listă de piese în CutOptim, acel program întreabă direct motorul și afișează planul acolo unde se lucrează deja.
  • Se construiește un software pentru tine. De un programator intern, de o firmă locală de software sau de furnizorul mașinii tale. Engine API este ceea ce conectează ei.

Folosirea Engine API înseamnă că cineva scrie software care îl apelează. Nu există interfață, nu există niciun tabel de completat și nu ai nimic de instalat — este un serviciu pentru programe, iar munca este făcută de cine scrie acel program. Dacă nimeni de partea ta nu scrie cod, aplicația este ceea ce îți trebuie.

Dacă nu ești sigur de care parte a liniei te afli, un test bun: ar putea apărea planul fără ca nimeni să îl ceară? Dacă da, API-ul este relevant. Dacă întotdeauna o persoană decide să facă un plan de tăiere, aplicația este deja instrumentul potrivit.


Ce face

Software-ul tău trimite aceleași două lucruri pe care le-ai introduce în aplicație — o listă de piese și o listă de material de bază — ca JSON. Motorul trimite înapoi un răspuns complet:

  • Layoutul complet. Fiecare piesă, poziționată pe o anumită placă sau bară, inclusiv dacă a fost rotită.
  • Un plan de tăiere. Nu doar o imagine cu dreptunghiuri: secvența reală de tăiere ghilotină, în ordine, astfel încât planul să poată fi executat pe un ferăstrău pentru panouri.
  • Cifrele. Câte plăci sau bare consumă lucrarea, procentul de randament, câte tăieri sunt necesare și prețul total al materialului folosit. Pentru panouri primești și cele două numere oneste de tăieri — linii de tăiere, care unifică tăierile ce împart aceeași reglare a opritorului, și treceri de ferăstrău, care numără fiecare trecere — plus lungimea totală tăiată.
  • Opțional, desenul. Cere include: ["svg","csv","dxf"], iar răspunsul poartă în plus layoutul ca fișier gata făcut — un desen SVG 2D de sine stătător, un DXF R12/AC1009 sau o listă de tăiere CSV — inline în JSON, fără stocare și fără un al doilea apel. (SVG este doar 2D.) În cererile 2D poți cere și labels (date de etichetă pe piesă), planHash (o amprentă a planului), pdf (PDF-ul planului de tăiere) și labelsPdf (PDF-ul etichetelor) — PDF-urile codate base64, desenate cu același cod ca aplicația.
  • Propriii tăi identificatori, returnați. Atașează un obiect meta — un număr de articol, o linie de comandă, o referință de client — oricărei piese sau oricărui rând de material, iar el revine neschimbat pe fiecare piesă plasată și pe fiecare placă sau bară, astfel încât planul să se potrivească cu propriul tău sistem. Acesta este câmpul de folosit când vrei să trimiți toate plăcile tale, să marchezi fiecare cu propriul tău cod și să citești înapoi ce placă a ales optimizatorul — pui codul în stock[].meta și îl primești identic pe sheets[].meta. Nu influențează niciodată plasarea. Nu folosi câmpul material pentru identificare: material este o partiționare strictă — o piesă este tăiată doar din material de bază care poartă aceeași etichetă material —, așa că etichetarea fiecărui rând de material, lăsând piesele neetichetate, face ca toate piesele să revină ca unmatched, iar rezultatul să fie gol.

Sunt patru moduri de optimizare, toate corespunzând aplicației — unul pentru plăci 2D, unul pentru material 1D liniar (bare, profile, țeavă), unul pentru lemn, al cărui material are o secțiune, și nesting-ul true-shape (POST /v1/optimize/nest), care aranjează poligoane arbitrare pentru tăiere cu laser, plasmă și jet de apă (modul Nesting al aplicației). Fiecare endpoint de optimizare are și un endpoint gratuit de validare, care verifică o cerere fără să o rezolve (vezi mai jos).

Endpointuri

URL-ul de bază este https://api.cutoptim.com. Endpointurile de optimizare și de consum poartă o cheie în antetul Authorization: Bearer <key>; endpointurile de validare și de disponibilitate nu au nevoie de cheie.

Endpoint Ce face
POST /v1/optimize/2d optimizare 2D pentru panouri
POST /v1/optimize/1d optimizare 1D / liniară — bare, profile, țeavă
POST /v1/optimize/wood Optimizarea lemnului — 1D cu potrivirea secțiunii
POST /v1/optimize/nest Nesting true-shape — poligoane neregulate pentru laser, plasmă și jet de apă
POST /v1/validate/2d · /1d · /wood · /nest Validează o cerere fără s-o rezolve — gratuit, fără cheie, fără cotă
GET /v1/jobs/{id} Interoghează o lucrare asincronă a motorului max — doar propriile lucrări, fără cotă
POST /v1/import/nest Citește conturul pieselor dintr-un fișier SVG sau DXF — necesită o cheie, nu consumă cotă
GET /v1/usage consumul și cota CONTULUI în luna curentă (toate cheile împart una)
GET /v1/health verificare de disponibilitate — fără cheie

Cele mai multe apeluri primesc direct rezultatul final. Singura excepție este motorul asincron max (vezi Trei motoare mai jos): o trimitere max returnează un id de lucrare, iar tu interoghezi GET /v1/jobs/{id} până când planul este gata.

Endpointurile de validare preiau același corp ca endpointul de optimizare corespunzător și îl verifică fără a rula rezolvarea: o cerere malformată revine ca un 400 care numește exact câmpul greșit, iar una bine formată returnează valid: true plus avertismente de fezabilitate (de exemplu, o piesă care nu încape în niciun material). Nu costă nimic și nu au nevoie de cheie, așa că îți poți valida payload-urile în timp ce construiești integrarea — încă înainte de a avea o cheie — și poți confirma că o cerere nu va fi respinsă fără să consumi unul dintre apelurile tale lunare.

Direcția fibrei la panouri

Placajul și plăcile furniruite au fibră, iar o piesă vizibilă trebuie tăiată cu fibra mergând în direcția corectă. Pe POST /v1/optimize/2d, trimite grain pe un rând de stoc — "w" sau "h", latura plăcii de-a lungul căreia merge fibra — și grain pe o piesă, latura piesei de-a lungul căreia trebuie să meargă. Fiecare astfel de piesă este plasată cu fibra de-a lungul fibrei plăcii sale: rotită cu 90° când asta este necesar (rotated: true pe plasare, ca la orice rotire), iar rotatable este ignorat pentru ea. O piesă fără grain se rotește în continuare liber, și pe un rând de stoc fără grain (MDF, melaminat); o piesă CU grain își păstrează și pe un astfel de rând orientarea pe care i-o dau rândurile cu fibră — material separă plăcile cu fibră de cele simple. O piesă care ar încăpea doar rotită la 90° împotriva fibrei apare în unplaced la dimensiunea trimisă, o linie din warnings o numește, iar POST /v1/validate/2d o semnalează înainte să se consume un apel.

Rândurile de stoc ale căror fibre merg în direcții diferite pot sta într-o singură cerere — un 2440 × 1220 cu "w" și un 1220 × 2440 cu "h" — iar fiecare placă revine în orientarea propriului rând, cu grain repetat în sheets[]. Cu material, o piesă este ținută de o fibră doar când propriul ei material are o placă cu fibră. grain-ul unei piese, fără stoc cu fibră în cerere, nu are niciun efect, iar o linie din warnings spune asta. options.trim și un options.firstCut forțat se aplică fiecărei plăci în orientarea propriului rând, inclusiv pe un rând a cărui fibră merge în cealaltă direcție. Modul Direcția fibrei din aplicația CutOptim rulează același cod. (Începând cu 2026-10-02.)

Potrivirea fibrei la panouri (seturi cu fibră potrivită)

Direcția fibrei păstrează fibra fiecărei piese în direcția corectă. Unele fronturi cer mai mult: un front de sertar deasupra a două uși al cărui desen continuă de la una la alta, ca și cum cele trei ar fi încă o singură placă. Pe POST /v1/optimize/2d, dă acelor rânduri de piese un id și numește-le în matchedSets:

{
  "parts": [
    { "id": "DF", "name": "Drawer front", "w": 48.125, "h": 6 },
    { "id": "DOOR", "name": "Door", "w": 24, "h": 30, "qty": 2 },
    { "name": "Shelf", "w": 22.5, "h": 11.25, "qty": 4 }
  ],
  "stock": [{ "w": 96, "h": 48, "qty": 2, "grain": "w" }],
  "options": { "kerf": 0.125 },
  "matchedSets": [
    { "id": "base-1", "name": "Base cabinet fronts", "grain": "w",
      "layout": { "dir": "rows", "lines": [["DF"], ["DOOR", "DOOR"]] } }
  ]
}
  • Ce este un set. layout.lines listează membrii după parts[].id. Cu dir: "rows" fiecare linie este un rând de membri una lângă alta, iar rândurile se așază de sus în jos, deci [["DF"], ["DOOR", "DOOR"]] este un front de sertar deasupra a două uși; cu "cols" fiecare linie este o coloană, iar coloanele stau una lângă alta. O piesă poate apărea de mai multe ori într-un set (Door, Door), dar poate aparține unui singur set. qty (implicit 1) este câte instanțe îți trebuie — trei corpuri identice înseamnă qty: 3 — iar qty-ul propriu al pieselor trebuie să acopere fiecare instanță. Un set are cel puțin 2 și cel mult 24 de membri, iar o cerere acceptă cel mult 50 de seturi.
  • Cum se taie. Setul trece prin optimizator ca un singur dreptunghi — blocul — și revine ca membrii lui, la exact un kerf distanță, dintr-o singură bucată de placă. grain-ul setului ("w" sau "h", de-a lungul lățimii sau înălțimii blocului) decide direcția fiecărui membru; grain-ul propriu al unui membru nu este folosit în interiorul setului, iar un avertisment numește orice membru pe care îl înlocuiește. Fără grain pe set, blocul se poate roti atunci când fiecare membru este rotatable. installGap este distanța dintre membri pe corp (implicit: kerf-ul); pe placă ei rămân la un kerf distanță.
  • Ce revine. Fiecare membru plasat poartă matchedSet: id-ul setului, ce instance este și position în ordinea de citire pe fața corpului — de sus în jos, de la stânga la dreapta, începând de la 1 — plus un hint precum "left" sau "right" acolo unde nu e ambiguu. Răspunsul adaugă un rezumat matchedSets, câte o intrare pe set: letter (A, B … în ordinea cererii), câte instanțe au fost tăiate ca bloc (asBlock), împărțite sau lăsate neplasate, dimensiunea blocului și warnings ale setului. Când un bloc nu încape pe nicio placă, onMiss: "split" (implicit) plasează membrii unul câte unul cu un avertisment, iar onMiss: "unplaced" îi listează în unplaced.
  • Avertismente, nu erori. O dimensiune care nu se aliniază este un avertisment pe set, nu un refuz. Fiecare linie începe cu codul ei — align: (liniile nu sunt la același nivel), gap: (kerf-ul este mai lat decât installGap), grain:, split:, unplaced:, unmatched: (nu există stoc din materialul setului), priority: și grainGroup: — iar align și gap sunt judecate la 1/64 din unitatea ta sau un sfert de kerf, care dintre ele e mai mică. Un set care nu poate fi aranjat deloc — un id de membru pe care nu-l poartă nicio piesă, un id referit pe două piese, mai puțin de doi membri, prea puține piese pentru qty — este un 400 care numește câmpul exact, înainte ca un apel să fie taxat.
  • parts[].id poate fi trimis în siguranță. Doar un id la care se referă un set este verificat (un șir imprimabil nevid de cel mult 64 de caractere sau un întreg, pe exact o piesă). Orice alt id este ignorat, oricât ar conține, deci numerele de articol din ERP pot rămâne pe rânduri. Și nimic nu se schimbă pentru o cerere fără seturi: doar un array matchedSets nevid activează funcția — absent, null, [] sau orice valoare care nu este array primește exact același răspuns ca înainte.
  • Exporturi. Cu seturi, csv primește la final coloanele Set și Position, svg tipărește codul de poziție (A1, A2 …) în etichetele pieselor și desenează cadrul fiecărui set într-un grup separat matched-sets — options.setOutlines: false lasă grupul deoparte — iar dxf poartă codul de poziție pe stratul LABELS. pdf și labelsPdf nu marchează seturile: desenează membrii ca piese obișnuite, iar warnings spune asta; marcajele setului sunt în sheets[].parts[].matchedSet, csv și svg.
  • Motoare și endpointuri. Motoarele heuristic și balanced aranjează seturi (balanced nu ierarhizează priority, deci sub respectStock un set își poate pierde locul acolo, cu un avertisment priority:). Motorul max refuză un matchedSets nevid cu un 400 al cărui details.unsupported îl numește, înainte ca un apel să fie taxat; unul gol este o lucrare max obișnuită. matchedSets și parts[].id sunt doar pentru 2D: endpointurile 1D, wood și nest le ignoră.
  • grainGroup este depreciat. Este încă acceptat și funcționează exact ca înainte: piesele care împart un grup sunt ținute pe o singură placă. Nu le-a plasat niciodată una lângă alta, deci nu dă fibră continuă între ele — pentru asta, folosește matchedSets.

Potrivirea fibrei din aplicația CutOptim aranjează seturile cu același nucleu.

De ce lemnul are endpoint propriu

Materialul liniar cunoaște o singură dimensiune, lungimea, așa că orice bară poate servi oricărei piese. La lemn nu este așa: o piesă 50×150 nu poate ieși dintr-o bară 50×100, oricâtă lungime ar rămâne. De aceea endpointul pentru lemn preia ambele laturi ale secțiunii pentru fiecare piesă și fiecare rând de material, împarte lucrarea pe secțiuni, potrivește fiecărei secțiuni materialul ei și returnează secțiunile separat — fiecare cu barele și totalurile proprii, alături de cifrele pentru întreaga lucrare.

Două detalii de știut înainte de integrare:

  • Cele două laturi ale secțiunii pot fi trimise în orice ordine. 50×100 și 100×50 sunt aceeași grindă întoarsă și formează o singură secțiune. Astfel, o diferență în felul în care au fost introduse datele tale nu poate face materialul să dispară.

  • „Niciun material de această secțiune” și „nu a încăput” se raportează separat. Primul înseamnă material lipsă, al doilea o problemă de capacitate, iar rezolvarea diferă — amestecate într-o singură listă, l-ar trimite pe utilizatorul tău să caute în locul greșit.

Ai putea aproxima asta cu mai multe apeluri 1d proprii, grupând piesele singur. Te-ar costa o cerere din cotă pentru fiecare secțiune în loc de una pentru lucrare, ar muta potrivirea materialului în codul tău și ar produce un total pe care ar trebui să-l compui singur — și care nu ar coincide neapărat cu ce arată aplicația CutOptim pentru aceeași lucrare.


Piese dintr-un fișier CAD

Endpointul de nesting nu acceptă doar coordonate. O piesă poate purta în schimb un source — un document SVG sau DXF — iar serverul îi extrage conturul, și găurile din el, din fișier. Este același cititor pe care aplicația îl folosește când tragi un desen peste modul ei Nesting, deci o bibliotecă de piese care există deja ca fișiere CAD nu trebuie rescrisă mai întâi în liste de coordonate.

Fișierul înlocuiește doar geometria. Cantitatea, materialul, rotațiile permise și propriile tale metadate rămân câmpuri obișnuite ale rândului piesei, exact ca atunci când trimiți coordonate. Un fișier descrie o piesă; când un singur desen conține mai multe componente separate, POST /v1/import/nest îl împarte întâi în rânduri gata de folosit — iar acel apel necesită o cheie, dar nu consumă o cerere din cota ta lunară.

Nimic nu se stochează. Fișierul există doar ca cererea însăși: este citit în memorie și dispare în momentul în care răspunsul este scris. Nu rămâne nicio copie pe disc sau într-o bază de date, nimic nu ajunge într-un jurnal și nu este nimic de șters după aceea. Cu unitățile procedăm la fel — un DXF poate declara milimetri sau inci și noi raportăm ce a spus, dar coordonatele nu sunt niciodată convertite, fiindcă nicio valoare din acest API nu poartă o unitate.

Același răspuns de fiecare dată

Motorul este determinist: aceeași intrare produce întotdeauna același rezultat. Nu există aleatoriu și nu există ceas în algoritm.

Sună academic, dar este exact motivul practic pentru care merită să construiești pe el. Înseamnă că rezultatele pot fi puse în cache — dacă ai întrebat deja despre exact aceeași lucrare, poți refolosi liniștit răspunsul în loc să întrebi din nou. Înseamnă și că integrarea poate fi testată: un plan poate fi comparat cu un rezultat cunoscut ca bun, iar o diferență este o diferență reală, nu zgomot. Un software care dă luni un preț unui client va da vineri același preț.

Există o singură excepție opțională, și o spune ea însăși: motorul max pentru nesting (mai jos) cheltuiește un buget de timp fix căutând, așa că până unde ajunge depinde de câtă muncă încape în acel timp. Răspunsurile sale poartă deterministic: false. Orice alt motor — inclusiv cel implicit pentru nesting, lbf — este determinist.

Reîncercări sigure. Dacă se întrerupe conexiunea, nu știți dacă cererea a ajuns. Trimiteți antetul Idempotency-Key — o valoare aleasă de dumneavoastră pentru fiecare lucrare — și reîncercați cu aceeași cheie: timp de 24 de ore, aceeași cerere returnează răspunsul salvat, marcat Idempotency-Replayed: true, și nu se taxează a doua oară. Nici o lucrare max nu intră de două ori în coadă. Cheia demo publică ignoră acest antet. (Din 2026-10-15.)

Webhookuri pentru lucrările asincrone. În loc să interogați GET /v1/jobs/{id}, înregistrați un endpoint (un URL https://) în panou și primiți un POST semnat — job.succeeded sau job.failed — când o lucrare max asincronă se termină. Verificați antetul CutOptim-Signature cu secretul primit, răspundeți în 10 secunde și citiți planul cu GET /v1/jobs/{id}. O livrare eșuată se reîncearcă: 8 încercări în 24 de ore. (Din 2026-10-19.)

SDK-uri oficiale. Clienți open source pentru TypeScript, Python și PHP — npm install @cutoptim/engine, pip install cutoptim, composer require cutoptim/engine — cu cereri tipizate, reîncercări care nu se taxează niciodată de două ori (fiecare apel poartă un Idempotency-Key), un ajutor pentru așteptarea lucrărilor asincrone și verificarea webhookurilor. Codul pe GitHub; detalii în ghidul SDK (în engleză).

Server MCP pentru asistenți AI. Claude Code, Cursor, VS Code și Claude Desktop pot apela motorul ca instrumente prin serverul Model Context Protocol găzduit la https://api.cutoptim.com/mcp, cu aceeași cheie API (Authorization: Bearer …) și din aceeași cotă: un apel de instrument este un apel API, iar instrumentele validate_* sunt gratuite. Rulează și local, cu pachetul npx -y @cutoptim/mcp (cheia în CUTOPTIM_API_KEY), iar MCP Registry oficial îl listează ca io.github.cutoptim/engine. Configurațiile clienților sunt în ghidul MCP (în engleză).


Trei motoare

API-ul oferă mai multe variante de motor. Primele două rulează sincron; al treilea este asincron. Diferența nu este de calitate — este un compromis între viteză, faptul că rezultatul poate fi tăiat sau nu pe un ferăstrău pentru panouri și cât de aproape ajunge de minimul teoretic.

  • heuristic este cel implicit și este același pe care îl folosește aplicația. Produce aranjamente ghilotină: cel mai bun randament, fiecare aranjament tăiabil pe ferăstrău și întotdeauna un plan de tăiere complet. Sincron.
  • balanced se activează explicit. Folosește în schimb nesting liber, care este dramatic mai rapid la lucrările foarte mari — măsurat aproximativ 25× mai rapid la o lucrare de 2.000 de piese — cu prețul unui randament puțin mai mic. Reținerea importantă: aranjamentele sale adesea nu pot fi tăiate de la o margine la alta, așa că pentru acelea nu returnează niciun plan de tăiere. Sincron.
  • max se activează explicit, pentru panouri 2D (și, separat, pentru nesting true-shape — vezi mai jos). La 2D este o căutare în arbore pe server care atinge optimul demonstrat pe mult mai multe lucrări decât cel implicit, iar aranjamentele sale rămân tăiabile ghilotină. Costul este timpul: o rezolvare max durează de la câteva secunde până la un minut, deci nu răspunde în cadrul răspunsului. În schimb, POST /v1/optimize/2d cu engine: "max" returnează un id de lucrare, iar tu interoghezi GET /v1/jobs/{id} până când este gata. Rămâne determinist. Apelează la el atunci când o lucrare mare și valoroasă merită așteptarea pentru ultimele câteva plăci. Modelează un singur format de stoc la dimensiunea completă a plăcii, cu disponibilitate nelimitată, așa că o cerere care mai poartă un al doilea format de stoc, trim pe laturi, stoc limitat (respectStock), materiale, grupuri de fibră sau un matchedSets nevid este refuzată din start cu un 400 care numește exact ce nu poate face — înainte ca un apel să fie taxat. Trimite acele lucrări către heuristic, care le modelează pe toate.

Nesting: lbf și max

Nesting-ul true-shape are propriile sale două motoare. lbf este cel implicit: instantaneu, sincron și determinist. max se activează explicit și este asincron, exact ca max la 2D — POST /v1/optimize/nest cu engine: "max" returnează un id de lucrare, iar tu interoghezi GET /v1/jobs/{id}.

max pentru nesting rulează întâi trecerea lbf, așa că are mereu un răspuns valid la îndemână. Apoi cheltuiește un buget de timp (options.timeBudgetMs, 60 de secunde implicit, între 10 și 180) căutând un aranjament cu mai puține plăci, umplând câte o placă odată. Nu returnează niciodată mai multe plăci decât lbf: când căutarea nu găsește nicio îmbunătățire, primești aranjamentul lbf și un avertisment care spune asta. Pentru că această căutare este limitată în timp, răspunsurile ei poartă deterministic: false. Acceptă mai multe dimensiuni de placă per material și respectStock, și își ordonează rezultatul cu aceeași regulă ca lbf (mai jos): înlocuiește planul lbf doar atunci când este mai bun — niciodată doar pentru că are mai puține plăci. O placă poligonală sau zonele de excludere, pe care căutarea sa în bandă nu le poate modela, sunt deservite de trecerea lbf din interiorul lucrării, cu un avertisment — niciodată refuzate. Vechiul nume sparrow este acceptat ca alias pentru max.

Piesele dreptunghiulare primesc o grilă exactă (din 2026-09-28). lbf găsește pozițiile prin eșantionare, iar aceasta aproape niciodată nu nimerește o grilă fără nicio rezervă: trei piese de 500 mm pe lățimea unei plăci de 1500 mm la spațiere zero încap exact, iar o căutare prin eșantionare așază doar două. De aceea ambele motoare încearcă și două alternative și o păstrează pe cea care se clasează cel mai bine după aceeași regulă: piesele restrânse la unghiurile drepte pe care le permit, și dreptunghiurile de încadrare ale pieselor așezate de un algoritm exact de așezare a dreptunghiurilor (dreptunghiurile care nu se suprapun nu pot conține piese care se suprapun, așa că metoda este validă pentru orice contur). La egalitate — aceleași plăci, aceeași arie de placă — câștigă planul care își umple plăcile în ordine, de la prima la ultima, apoi cel cu mai puține piese rotite în afara unghiurilor drepte. Nu este nimic de activat, iar prin această ordonare un rezultat poate doar să se îmbunătățească; un plan pe care dreptunghiurile îl aduc la cel mai mic număr de plăci permis de aria pieselor face și ca max să răspundă imediat, în loc să mai caute.

O lucrare cu câteva zeci de piese are de obicei nevoie de un buget de aproximativ 15 secunde (timeBudgetMs: 15000); lucrarea se termină la aproximativ una-două secunde după buget, plus timpul petrecut în coadă. Interoghează GET /v1/jobs/{id} la fiecare două-trei secunde — interogarea nu consumă cotă. Niciun buget nu poate promite un anumit număr de plăci.

Nesting: distanța de la marginea plăcii, dimensiunile plăcii și costul fiecărei plăci

  • Distanța de la margine. options.minSeparation este spațierea dintre piese și, de una singură, se aplică și la marginea plăcii. options.edgeClearance setează marginea separat — de exemplu 5 între piese și 0 sau 10 la margine. Omite-l și marginea păstrează minSeparation, exact ca înainte. Funcționează pe ambele motoare, are nevoie de plăci dreptunghiulare (w și h), iar zonele de excludere păstrează minSeparation, la fel ca piesele. O placă poligonală, sau o valoare care nu lasă loc pe placă, este refuzată cu un 400 înainte ca un apel să fie taxat.
  • Alegerea unei dimensiuni de placă. Când un material are două sau mai multe rânduri de material de bază, lbf le încearcă în ordinea ta, fiecare dimensiune separat și într-o ordine de la cel mai ieftin în sus, și o păstrează pe cea mai bună — așa că rezultatul nu mai depinde de ordinea în care listezi rândurile. Ordonarea este: cele mai multe piese de tăiat obligatoriu plasate (vezi mai jos), apoi cele mai multe piese plasate, apoi cea mai mică arie totală de placă (material), apoi cele mai puține plăci. Cu options.minimizeCost ordonează în schimb după prețul total (price, sau cost pentru un rând fără preț) — dar numai atunci când fiecare rând al acelui material poartă unul; altfel revine la arie și spune asta în warnings.
  • Amestecarea dimensiunilor. După aceea, fiecare placă — cea mai puțin umplută mai întâi — este renestuită pe cont propriu pe rândurile mai ieftine sau mai mici și înlocuită atunci când întregul plan clasează mai bine. Așa că dimensiunile pot fi amestecate în cadrul unui material: de obicei două plăci mari și una mai mică la final, acolo unde ultima placă pe jumătate goală era înainte una mare. Cu options.respectStock, niciun rând nu este folosit mai des decât qty al lui. Motorul max aplică aceeași ordonare.
  • Piese de tăiat obligatoriu. parts[].priority: true marchează o piesă care trebuie tăiată. Contează cu options.respectStock — o ofertă plafonată, unde nu toate piesele pot încăpea: piesele de tăiat obligatoriu sunt atunci plasate primele, așa că o piesă obișnuită nu ocupă niciodată spațiul de care are nevoie o piesă de tăiat obligatoriu, iar fiecare ordonare de mai sus pune înainte planul care păstrează mai multe dintre ele, chiar dacă plasează mai puține piese în total. Ambele motoare respectă asta (max păstrează aranjamentul lbf ori de câte ori rămâne ceva neplasat). Fără respectStock, orice piesă care încape este plasată oricum, așa că marcajul nu schimbă nimic. O piesă de tăiat obligatoriu care nu încape pe nicio placă rămâne totuși listată în unplaced. (Din 2026-09-22 — înainte, motorul de nesting accepta câmpul, dar îl ignora.)
  • Stoc limitat pe care nu încape tot. Cu options.respectStock, dacă planul lasă încă piese neplasate, motorul umple în plus plăcile una câte una cu dreptunghiurile de încadrare ale pieselor — fiecare cât de plină se poate, iar o piesă care încape doar pe o singură dimensiune de placă merge acolo prima (o latură înaltă pe singura placă mare, nu pe o fâșie de rest). Planul este preluat doar dacă plasează mai multe piese (cele obligatorii întâi) sau folosește mai puțin material; o lucrare la care încape tot revine exact ca înainte. Respectă rotațiile permise ale fiecărei piese, minSeparation și edgeClearance. (Din 2026-10-14.)
  • Ce a costat fiecare placă. Fiecare placă poartă stock — indexul rândului de material de bază din cerere din care a fost tăiată — iar răspunsul adaugă stockUsage: câte o intrare pentru fiecare rând de material de bază folosit, cu numărul de plăci, prețul total și densitatea. Unitatea este rândul de material de bază, nu dimensiunea: două rânduri cu aceleași dimensiuni, dar cu preț sau meta diferit, sunt două intrări.
  • Lungimea de tăiere și străpungerile. Fiecare placă poartă cutLength — perimetrul însumat al conturilor și al găurilor pieselor sale plasate, în unitatea ta — și pierces, unul per contur închis; metrics totalizează ambele. Este lungimea geometrică a conturului: fără tăiere pe linie comună, intrări de tăiere sau micro-îmbinări — CAM-ul tău le adaugă pe acelea.
  • Aria utilizată, pentru facturarea unei părți de placă. Fiecare placă poartă usedWidth și usedHeight — cel mai îndepărtat punct la care ajunge orice piesă plasată din colțul de origine al plăcii, în unitatea ta, pe placa reală (cu edgeClearance este inclus și golul de la margine) — și usedArea, produsul lor; stockUsage[].usedArea îl totalizează pe rând de material de bază. Asta îi trebuie unui ERP ca să factureze o tăiere orizontală (usedHeight × lățimea plăcii), o tăiere verticală (usedWidth × înălțimea plăcii) sau bounding box-ul (usedArea) în loc de placa întreagă — regula de facturare rămâne a ta. Ca să facă aceste cifre mici, ambele motoare compactează implicit placa cea mai puțin umplută a fiecărui material: piesele ei sunt renestuite pe aceeași placă cu subseturi de rotații din cele permise fiecărei piese — 0/180, 0/90/180/270 și o singură orientare pentru fiecare copie, intersectate cu un allowedRotations discret, niciodată un unghi nou — iar aranjamentul cu cea mai mică arie utilizată este păstrat. Cu engine: "max", placa respectivă este apoi rearanjată și de căutarea propriu-zisă — de-a lungul înălțimii plăcii și, dacă planul are o singură placă, și de-a lungul lățimii — și se păstrează, după aceeași regulă, aranjamentul mai strâns. Numărul de plăci, dimensiunile, prețul și piesele plasate nu se schimbă niciodată; options.compact: false returnează aranjamentul necompactat. Dacă facturezi o fâșie în loc de bounding box, setează options.compactFor pentru a alege: "horizontal" păstrează aranjamentul cu cea mai mică usedHeight (o fâșie pe toată lățimea plăcii), "vertical" pe cel cu cea mai mică usedWidth (o fâșie pe toată înălțimea plăcii); implicit "box" păstrează cea mai mică usedArea. Modurile de fâșie mai încearcă și fiecare copie rotită cu un sfert (90° sau 270°) acolo unde allowedRotations permite. Cât de mică ajunge aria utilizată depinde de piese. (Din 2026-09-22.)

balanced nu înseamnă „rezultate mai bune”. Este mai rapid și dă un randament puțin mai mic, iar când aranjamentul său nu este tăiabil ghilotină nu există niciun plan de tăiere de dat unui operator de ferăstrău. Alege-l doar când viteza la o lucrare foarte mare contează mai mult decât un plan gata de ferăstrău. Dacă nu ești sigur, rămâi pe varianta implicită.


Limite

Fiecare cerere este mărginită, așa că o lucrare scăpată de sub control eșuează clar, în loc să rămână blocată:

Limită Valoare
Piese per cerere 2.000
Rânduri de material per cerere 50
Dimensiunea corpului cererii 1 MB
Dimensiunea corpului cererii — rutele nest care pot purta un desen 10 MB
Chei active per cont 10
Apeluri validate fără cheie per adresă 120 / minut
Chei API necunoscute per adresă 30 / minut — apoi 429 pentru restul minutului
Așteptare pentru un loc de calcul liber (trasee sincrone) circa 8 s — apoi 429, nu se taxează nimic
Lucrări max în queued/running per cont 5
Bugetul de căutare al max pentru nesting, per lucrare 10–180 s (implicit 60 s)
Păstrarea Idempotency-Key 24 de ore
Endpointuri webhook pe cont 5
Încercări de livrare webhook 8 în 24 de ore

Obținerea accesului

Pornește de la pagina Engine API. Engine API se facturează separat de planurile aplicației și nicio schimbare de plan nu îl activează.

  1. Încearcă, apoi abonează-te — sau scrie-ne. Poți apela API-ul înainte să plătești: butoanele Rulează acest exemplu din documentația API folosesc o cheie demo publică, iar orice cont autentificat poate crea în panou chei de test gratuite (propria alocare lunară mică, nu se facturează niciodată, fără abonament). Când ești gata, abonarea din pagina Engine API este calea cea mai rapidă — planul de intrare, Studio, începe cu o perioadă de probă gratuită, iar accesul ajunge singur în cont. Dacă preferi să descrii mai întâi integrarea sau ai nevoie de un volum peste planul standard, scrie-ne și spune ce vrei să conectezi și aproximativ câte planuri de tăiere pe lună va fi nevoie.
  2. Accesul este adăugat pe contul tău. Nimic altceva la contul tău nu se schimbă.
  3. Creează o cheie. Cardul Chei API este în panoul de control pentru orice cont autentificat: fără abonament creează chei de test, cu acces API și chei live. Îți creezi, denumești și ștergi singur cheile de acolo.
  4. Copiază imediat cheia. Cheia completă este afișată exact o singură dată, în momentul în care o creezi.

O cheie este afișată o singură dată. CutOptim stochează doar un hash sha256 al ei, niciodată cheia în sine — deci nu poate fi citită înapoi mai târziu, nici de tine, nici de noi. Copiază-o direct în configurația software-ului tău atunci când o creezi. Dacă pierzi o cheie, șterge-o și creează una nouă; dacă o cheie ajunge vreodată să fie expusă, șterge-o și apelurile încetează să funcționeze imediat.

Tratează o cheie ca pe o parolă: locul ei este în configurația software-ului tău, nu într-un email, într-un tabel sau într-o captură de ecran.

Ce face cardul Chei API din panoul tău

Patru comenzi — și merită spus exact ce schimbă fiecare, mai ales ultima, despre care mulți cred că ține de facturare. Nu ține.

  • Plan, schimbarea planului și Facturare. Arată pe ce plan se află contul (Studio sau Scale). Treci la Scale (sau Treci la Studio) schimbă planul după o confirmare, iar cota lunară a contului se modifică imediat. Facturare deschide setările tale de facturare, unde actualizezi cardul, vezi facturile sau anulezi.
  • Creează cheie. Generează o cheie nouă și o afișează o singură dată, chiar acolo. Numele (Integrare ERP, staging) există doar ca să le deosebești mai târziu. Până la 10 chei active per cont. Cheile de test se creează la fel și se numără separat: au propria alocare lunară mică și nu se facturează niciodată.
  • Bara de consum. Două cifre: totalul contului pe luna calendaristică față de cotă și, pentru fiecare cheie, cât a consumat ea. Cifra pe cheie răspunde la care integrare consumă alocarea — nu este un buget separat.
  • Revocă. Scoate din uz acea singură cheie, începând cu următorul apel. Rândul rămâne vizibil, ca istoricul să nu se piardă.

Revocarea unei chei nu are legătură cu abonamentul. Nu anulează nimic, nu returnează bani și nu eliberează cotă — planul merge mai departe și alocarea rămâne, doar că nu mai deții acea cheie. Revocă atunci când o cheie a fost expusă sau o integrare este retrasă. Ca să nu mai fii facturat, anulează abonamentul: accesul continuă până la finalul perioadei deja plătite, iar după aceea încetează să funcționeze și cheile existente.

O singură cotă pentru cont, nu una pentru fiecare cheie

Fiecare cheie activă a contului consumă din aceeași alocare lunară. A doua cheie nu creează o a doua cotă — cheile există ca să separi staging-ul de producție, să dai fiecărei integrări propria credențială și să revoci una fără să le deranjezi pe celelalte.

GET /v1/usage raportează situația contului (used, limit, remaining), deci răspunde la întrebarea pe care o ai de fapt — cât a mai rămas până când apelurile încep să eșueze — indiferent de cheia cu care ai întrebat. Când alocarea se termină, fiecare cheie returnează 402, nu doar cea care a consumat-o.


Planuri, preț și cotă

Engine API este facturat separat de planurile aplicației, lunar, în EUR, cu două planuri:

Plan Ce diferă
Studio Planul de intrare, cu perioadă de probă gratuită
Scale O cotă lunară de cereri mai mare, fără perioadă de probă — treci la el de la Studio

Restul este la fel în ambele: aceleași motoare, toate cele patru moduri, fiecare opțiune, aceleași răspunsuri. Fiecare cerere contează la fel — o lucrare de nesting costă o cerere, exact ca una 2D sau 1D.

  • Plafon strict, fără depășiri. Când cota lunară s-a epuizat, apelurile returnează 402 până când aceasta se resetează în prima zi a lunii următoare. Nu există factură-surpriză.
  • Două e-mailuri, ca plafonul să nu te ia prin surprindere. Trimitem un e-mail contului la 90% din cotă și încă unul când aceasta este epuizată.
  • Schimbarea planului se face dintr-un singur buton de pe cardul Chei API din panoul tău (Treci la Scale / Treci la Studio); noua cotă se aplică imediat. O trecere la un plan superior se taxează pe loc pentru restul perioadei; o trecere la un plan inferior nu se rambursează, iar prețul mai mic se aplică de la următoarea reînnoire. Schimbarea este disponibilă după perioada de probă.
  • Volumele mai mari decât planul Scale se tarifează individual — scrie-ne.

Prețurile și cotele actuale sunt listate pe pagina Engine API — acea pagină le citește din configurația noastră de prețuri, deci cifra de acolo este întotdeauna cea corectă.

Pentru detaliile tehnice — structura exactă a cererii și a răspunsului, fiecare opțiune, toate codurile de eroare și modul în care funcționează versionarea — vezi documentația API.


Componente open-source

Motoarele CutOptim se bazează pe biblioteci open-source, folosite nemodificate pe serverele noastre:

  • jagua-rs — motorul geometric de coliziune din spatele nesting-ului true-shape (MPL-2.0).
  • sparrow — căutarea din spatele motorului max pentru nesting (MIT, KU Leuven).
  • PackingSolver — căutarea în arbore din spatele motorului max pentru 2D (MIT).

Tot ce este în jurul lor — API-ul, corespondența dintre contract și aceste motoare, packerele dreptunghiulare și aplicația însăși — este cod propriu CutOptim.


Ce nu se schimbă

Merită spus limpede, pentru că Engine API este ușor de citit greșit ca o schimbare a produsului:

  • Optimizatorul din aplicație este neschimbat. Rulează în continuare în browserul tău, exact ca înainte.
  • Gratuit, Pro și Atelier nu sunt afectate. Includ în continuare optimizatorul din aplicație, cu aceleași limite ca înainte. Nimic nu a fost mutat în spatele API-ului.
  • Nimic din ce faci în aplicație nu consumă cereri API. Cota lunară de API este atinsă doar de apelurile făcute de propriul tău software.

Engine API este o adăugire pentru cei care integrează CutOptim în alt software. Dacă nu este cazul tău, nimic nu s-a schimbat.

FAQ

Care este diferența dintre planurile Studio și Scale?
Doar numărul de cereri pe lună și perioada de probă. Ambele planuri rulează aceleași motoare, toate cele patru moduri și fiecare opțiune, iar fiecare cerere contează la fel — o lucrare de nesting costă o cerere, exact ca una 2D. Studio este planul de intrare și vine cu o perioadă de probă gratuită; Scale are o cotă lunară mai mare și nu are perioadă de probă, pentru că ajungi la el trecând de la Studio. Prețurile și cotele actuale se află pe pagina Engine API.
Pot trece de la Studio la Scale și invers?
Da, după încheierea perioadei de probă și după prima plată reușită, cu butonul Treci la Scale (sau Treci la Studio) de pe cardul Chei API din panoul tău. Noua cotă lunară se aplică imediat contului tău. O trecere la un plan superior se taxează pe loc pentru restul perioadei de facturare; o trecere la un plan inferior nu se rambursează, iar prețul mai mic se aplică de la următoarea reînnoire.
Pot încerca API-ul înainte să plătesc?
Da, în două feluri. Documentația API are butoane Rulează acest exemplu care folosesc o cheie demo publică, fără niciun cont — doar lucrări mici. Iar orice cont CutOptim autentificat poate crea chei de test în panou: au propria alocare lunară mică, nu se facturează niciodată și nu cer abonament, așa că poți construi toată integrarea înainte să cumperi. Studio începe apoi cu o perioadă de probă gratuită.
Voi fi avertizat înainte să se termine cota lunară?
Da. Trimitem un e-mail contului la 90% din cota lunară și încă unul când aceasta s-a epuizat. După aceea, apelurile returnează 402 până când cota se resetează în prima zi a lunii următoare — sau imediat, dacă treci la planul mai mare.
Am nevoie de Engine API?
Aproape sigur nu. Dacă tai panouri sau bare deschizând CutOptim în browser, aplicația face deja tot ce face API-ul — API-ul este același motor, doar fără ecran. Există pentru o singură situație: alt software are nevoie de planuri de tăiere fără ca o persoană să deschidă aplicația. Dacă nimeni nu scrie cod care să folosească CutOptim, îl poți ignora.
Pentru cine este de fapt Engine API?
Pentru două tipuri de client: cineva care folosește deja un software în care ar trebui să stea planul de tăiere — un ERP, o aplicație de ofertare sau de preluare a comenzilor, software-ul propriu al unei mașini — și cineva pentru care se construiește un astfel de software, de către un programator intern sau o firmă. În ambele cazuri, munca este făcută de cine scrie acel software, nu de tine în interfața CutOptim.
Cum obțin acces la Engine API?
Te poți abona direct din pagina Engine API — are o perioadă de probă, iar accesul ajunge singur în cont. Este calea cea mai rapidă. Dacă preferi să descrii mai întâi integrarea sau ai nevoie de un volum peste planul standard, scrie-ne. În ambele cazuri îți creezi apoi singur cheile live din cardul Chei API din panoul tău. Engine API se facturează separat de planurile aplicației și nicio schimbare de plan nu îl activează.
Engine API taie și lemn sau doar plăci și bare?
Toate cele patru moduri pe care le are aplicația: plăci, bare, lemn și nesting true-shape. Endpointul pentru lemn cunoaște secțiunea: piesele și materialul poartă ambele laturi ale secțiunii, așa că o piesă 50×150 se taie doar din material 50×150. Lucrarea se împarte pe secțiuni și fiecare secțiune revine cu barele și totalurile proprii, iar cererea pentru a cărei secțiune nu există deloc material este raportată separat de piesele care aveau material și nu au încăput.
Engine API îmi schimbă planul Gratuit, Pro sau Atelier?
Nu. Engine API este un supliment separat și nu schimbă nimic la planurile obișnuite. Optimizatorul din aplicație este neschimbat, rulează în continuare în browserul tău și rămâne inclus în Gratuit, Pro și Atelier exact ca înainte. Nimic din ce faci în aplicație nu consumă cereri API.
Există un SDK sau o bibliotecă client pentru Engine API?
Da. Există SDK-uri oficiale open source pentru TypeScript (npm @cutoptim/engine), Python (PyPI cutoptim) și PHP (Composer cutoptim/engine) — codul pe github.com/cutoptim, ghidul la /engine/reference/guides/sdks. Sunt opționale: API-ul rămâne HTTPS simplu cu JSON, pe care orice limbaj îl poate apela fără un pachet CutOptim. Pentru lucrările asincrone există webhookuri: înregistrați un endpoint în panou și primiți un POST semnat când o lucrare max se termină, în loc să interogați. Cele mai multe apeluri primesc direct rezultatul final; singura excepție este motorul asincron max — pentru panouri 2D și pentru nesting true-shape —, unde POST /v1/optimize/2d sau /v1/optimize/nest cu engine "max" returnează un id de lucrare pe care îl interoghezi cu GET /v1/jobs/{id} până când rezultatul este gata.
Motorul balanced este mai bun decât cel implicit?
Nu — este un compromis, nu o îmbunătățire. Motorul implicit heuristic dă cel mai bun randament, iar fiecare aranjament produs de el poate fi tăiat pe un ferăstrău pentru panouri, deci returnează întotdeauna un plan de tăiere. Motorul balanced este mult mai rapid la lucrările foarte mari, dar are un randament puțin mai mic, iar aranjamentele sale adesea nu pot fi tăiate de la o margine la alta, deci pentru acelea nu returnează niciun plan de tăiere. Folosește-l doar când viteza la o lucrare mare contează mai mult decât un plan gata de ferăstrău.
De ce cheia mea API este afișată o singură dată?
Pentru că CutOptim nu stochează niciodată cheia în sine — doar un hash sha256 al ei. Asta înseamnă că nimeni, nici noi, nu poate citi cheia înapoi din baza de date, așa că poate fi afișată doar în momentul în care este creată. Copiază-o imediat în configurația software-ului tău; dacă o pierzi, șterge cheia și creează una nouă.
Ce se întâmplă dacă revoc o cheie API — primesc banii înapoi?
Nu, și nici nu anulează ceva. Revocarea scoate din uz acea singură cheie de la următorul apel; abonamentul merge mai departe, iar cota lunară rămâne. Revocă o cheie atunci când a fost expusă sau o integrare este retrasă, apoi creează una de înlocuire. Ca să nu mai fii facturat, anulează abonamentul — accesul continuă până la finalul perioadei deja plătite, iar după aceea încetează să funcționeze și cheile existente.
Dacă creez mai multe chei API, primesc mai multe cereri?
Nu. Cota lunară aparține contului, iar fiecare cheie activă consumă din aceeași alocare — a doua cheie nu adaugă o a doua cotă. Cheile există ca să separi staging-ul de producție, să dai fiecărei integrări propria credențială și să revoci una fără să le deranjezi pe celelalte. Când alocarea se termină, fiecare cheie returnează 402, nu doar cea care a consumat-o. GET /v1/usage raportează situația contului, indiferent de cheia folosită.
Poate Engine API să returneze un desen, nu doar coordonate?
Da. Adaugă include: ["svg","csv","dxf"] la o cerere de optimizare, iar răspunsul poartă layoutul ca fișier gata făcut, inline în JSON: un desen SVG 2D de sine stătător, un DXF R12/AC1009 pe straturile STOCK/PARTS/LABELS sau o listă de tăiere CSV. Nu există stocare și niciun al doilea apel. SVG este doar 2D; o cerere 1D sau pentru lemn returnează în schimb un avertisment. Poți atașa de asemenea un obiect meta (numărul de articol din ERP, id-ul liniei de comandă sau referința clientului) oricărei piese sau oricărui rând de material, iar el revine identic la ieșire, astfel încât planul să se reconcilieze cu sistemul tău. meta este de asemenea câmpul potrivit pentru a citi înapoi ce placă a ales optimizatorul: pui codul tău în stock[].meta și îl primești identic pe sheets[].meta, iar el nu influențează niciodată plasarea. Nu folosi câmpul material pentru identificare: material este o partiționare strictă, așa că etichetarea fiecărui rând de material, lăsând piesele neetichetate, face ca toate piesele să revină ca unmatched, iar rezultatul să fie gol.
Pot verifica o cerere fără să consum unul dintre apelurile mele lunare?
Da. POST /v1/validate/2d, /v1/validate/1d, /v1/validate/wood sau /v1/validate/nest preia același corp ca endpointul de optimizare corespunzător și îl verifică fără să-l rezolve — gratuit, fără cheie API și fără cotă consumată. O cerere malformată revine ca un 400 care numește exact câmpul greșit, iar una bine formată returnează valid: true plus avertismente de fezabilitate (de exemplu, o piesă care nu încape în niciun material). Folosește-l ca să-ți validezi payload-urile în timp ce construiești integrarea, încă înainte de a deține o cheie.
Ce se întâmplă cu un fișier SVG sau DXF trimis către API?
Nu rămâne nimic din el. Fișierul călătorește ca și corp al cererii, este citit în memorie pentru a obține conturul piesei și dispare imediat ce răspunsul este scris — nicio copie pe disc, nicio copie în baza de date, nicio linie de jurnal care să îl conțină, deci nimic de șters după aceea și nicio perioadă de păstrare despre care să întrebi. Este aceeași lipsă de stare pe care o ține restul API-ului: nici planurile tale de croire nu le păstrăm mai mult decât cererea care le-a produs.
Are și nesting-ul true-shape un motor max?
Da. POST /v1/optimize/nest cu engine "max" este asincron la fel ca motorul max pentru 2D: apelul răspunde cu 202 și un id de lucrare, iar tu interoghezi GET /v1/jobs/{id}. Rulează întâi trecerea instantanee lbf, apoi cheltuiește un buget de timp — 60 de secunde implicit, între 10 și 180 prin options.timeBudgetMs — căutând un aranjament cu mai puține plăci, umplând câte o placă odată. Nu returnează niciodată mai multe plăci decât ar folosi lbf; când nu găsește niciuna, primești aranjamentul lbf și un avertisment care spune asta. Pentru că această căutare este limitată în timp, răspunsurile ei poartă deterministic: false. Acceptă mai multe dimensiuni de placă per material și respectStock, și își păstrează propriul rezultat doar atunci când clasează mai bine decât planul lbf (după preț cu options.minimizeCost, altfel după aria plăcii). O placă poligonală sau zonele de excludere, pe care căutarea sa nu le poate modela, sunt deservite de trecerea lbf din interiorul lucrării, cu un avertisment — niciodată refuzate.
De ce piesele dreptunghiulare de nesting au revenit înclinate sau pe o placă în plus?
Înainte de 2026-09-28 se putea întâmpla: motorul de nesting lbf găsește pozițiile prin eșantionare, așa că, cu rotație liberă, putea roti o piesă aproape dreptunghiulară cu o fracțiune de grad și rareori găsea o grilă fără nicio rezervă, cum ar fi trei piese de 500 mm pe lățimea unei plăci de 1500 mm la spațiere zero. Ambele motoare de nesting încearcă acum și piesele la unghiurile drepte pe care le permit și așază dreptunghiurile de încadrare ale pieselor cu un algoritm exact de așezare a dreptunghiurilor, păstrând planul care se clasează cel mai bine; la egalitate câștigă planul care își umple plăcile în ordine, de la prima la ultima, apoi cel cu mai puține piese înclinate. Nu trebuie să îți schimbi cererea. Dacă piesele tale nu trebuie să iasă niciodată de pe unghiurile drepte, trimite allowedRotations: [0, 90, 180, 270], ca înainte.
Pot seta distanța până la marginea plăcii separat de spațierea dintre piese?
Da. options.minSeparation este spațierea dintre piese și, de una singură, se aplică și la marginea plăcii. Adaugă options.edgeClearance pentru a seta marginea separat — de exemplu 5 între piese și 0 sau 10 la margine. Funcționează pe ambele motoare de nesting, iar dacă îl omiți, marginea păstrează minSeparation exact ca înainte. Are nevoie de plăci dreptunghiulare (w și h): cu o placă poligonală, sau cu o valoare care nu lasă loc pe placă, cererea este refuzată cu un 400 înainte ca un apel să fie taxat. Zonele de excludere păstrează minSeparation, la fel ca piesele.
Cum alege nesting-ul între mai multe dimensiuni de placă?
Când un material are două sau mai multe rânduri de material de bază, motorul lbf le încearcă în ordinea ta, fiecare dimensiune separat și într-o ordine de la cel mai ieftin în sus, și o păstrează pe cea mai bună — așa că răspunsul nu mai depinde de care rând îl listezi primul. Ordonează după cele mai multe piese de tăiat obligatoriu plasate (piesele marcate priority, ceea ce contează împreună cu options.respectStock), apoi cele mai multe piese plasate, apoi cea mai mică arie totală de placă; cu options.minimizeCost ordonează în schimb după prețul total (price, sau cost când un rând nu are preț), cu condiția ca fiecare rând al acelui material să aibă unul. Apoi fiecare placă, cea mai puțin umplută mai întâi, este renestuită pe cont propriu pe rândurile mai ieftine sau mai mici și înlocuită atunci când întregul plan clasează mai bine — așa că dimensiunile pot fi amestecate în cadrul unui material, de obicei două plăci mari și una mai mică la final. Cu options.respectStock niciun rând nu este folosit mai des decât qty al lui. Răspunsul spune din ce rând provine fiecare placă (sheets[].stock) și totalizează plăcile, prețul și densitatea pe rând (stockUsage). Motorul max aplică aceeași ordonare.
Pot marca piesele de nesting ca fiind de tăiat obligatoriu?
Da: parts[].priority: true. Contează atunci când oferta de plăci este plafonată (options.respectStock), pentru că atunci nu toate piesele pot încăpea: piesele de tăiat obligatoriu sunt plasate primele, așa că o piesă obișnuită nu ocupă niciodată spațiul de care are nevoie o piesă de tăiat obligatoriu, iar orice comparație între planuri clasează mai sus planul care păstrează mai multe dintre ele. Ambele motoare de nesting respectă asta. Fără respectStock, orice piesă care încape este plasată oricum, așa că marcajul nu schimbă nimic. O piesă de tăiat obligatoriu care nu încape pe nicio placă tot revine în unplaced. (Înainte de 2026-09-22, motorul de nesting accepta acest câmp, dar nu acționa în funcție de el.)
Are răspunsul de nesting lungimea de tăiere?
Da. Fiecare placă poartă cutLength — perimetrul însumat al conturilor exterioare și al găurilor pieselor sale plasate, în unitatea ta — și pierces, unul per contur închis (conturul fiecărei piese plus unul per gaură); metrics totalizează ambele pentru întreaga lucrare. Este lungimea geometrică a conturului: tăierea pe linie comună, intrările/ieșirile de tăiere și micro-îmbinările nu sunt incluse, pentru că CAM-ul mașinii tale le adaugă — deci este o bază solidă pentru timpul de mașină și consumabile, nu traseul final al sculei.
Pot factura doar partea de placă pe care o folosește un nesting?
API-ul îți dă cifrele; regula de facturare rămâne a ta. Fiecare placă poartă usedWidth și usedHeight — cel mai îndepărtat punct la care ajunge orice piesă plasată, măsurat din colțul de origine al plăcii, în unitatea ta — și usedArea, produsul lor; stockUsage[].usedArea îl totalizează pe rând de material de bază. O tăiere orizontală este usedHeight × lățimea plăcii, o tăiere verticală usedWidth × înălțimea plăcii, un bounding box usedArea. Ambele motoare de nesting mai compactează implicit și placa cea mai puțin umplută a fiecărui material: piesele ei sunt renestuite pe aceeași placă cu subseturi de rotații din cele permise fiecărei piese (0/180, 0/90/180/270, o singură orientare pentru fiecare copie — niciodată un unghi nou), iar aranjamentul cu cea mai mică arie utilizată este păstrat. Numărul de plăci, dimensiunile, prețul și piesele plasate nu se schimbă niciodată. options.compact: false returnează aranjamentul necompactat. Dacă facturezi o fâșie în loc de bounding box, setează options.compactFor la "horizontal" (înălțimea utilizată cea mai mică, pentru o fâșie pe toată lățimea plăcii) sau "vertical" (lățimea utilizată cea mai mică, pentru o fâșie pe toată înălțimea plăcii); implicit "box" minimizează aria utilizată. Cât de mică ajunge aria utilizată depinde de piese, așa că nicio fracțiune de placă nu poate fi promisă dinainte.
Cât buget de timp ar trebui să dau motorului max pentru nesting?
Lucrarea se termină cam la una-două secunde după bugetul alocat, plus timpul petrecut în coadă. Pentru o lucrare de câteva zeci de piese, 15 secunde (options.timeBudgetMs: 15000) sunt de obicei suficiente; valoarea implicită este 60 de secunde, iar intervalul este 10-180. Un buget mai mare dă căutării mai multe șanse să economisească o placă, dar niciun buget nu poate promite un anumit număr de plăci — asta depinde de piese și de spațiere. Interoghează GET /v1/jobs/{id} la fiecare două-trei secunde; interogarea nu consumă cotă.
Poate API-ul să respecte direcția fibrei unei piese?
Da. Pe POST /v1/optimize/2d, dă unui rând de stoc grain: "w" sau "h" — latura plăcii de-a lungul căreia merge fibra — și unei piese grain: "w" sau "h" — latura piesei de-a lungul căreia trebuie să meargă. Fiecare astfel de piesă este plasată cu fibra de-a lungul fibrei plăcii sale, rotită cu 90° când este nevoie (rotated: true), iar rotatable este atunci ignorat pentru ea. Rândurile de stoc ale căror fibre merg în direcții diferite pot fi amestecate. Cu material, contează doar plăcile din materialul propriu al piesei. Fiecare placă repetă grain-ul rândului ei. Dacă niciun rând de stoc nu are grain, grain-ul unei piese nu are niciun efect, iar warnings spune asta. Toate cele trei motoare 2D îl suportă (max cu singurul său rând de stoc obișnuit).
Poate API-ul să taie fronturi potrivite, astfel încât fibra să continue de la o piesă la alta?
Da, pe POST /v1/optimize/2d. Dă rândurilor de piese un id și numește-le în matchedSets — pentru un front de sertar deasupra a două uși, un layout cu dir rows și liniile [DF] și [DOOR, DOOR]. Setul este tăiat una lângă alta dintr-o singură placă, la exact un kerf distanță, iar fibra setului decide direcția fiecărui membru. Fiecare membru plasat revine cu matchedSet (id-ul setului, instanța și poziția lui), iar răspunsul adaugă un rezumat matchedSets ale cărui warnings spun, de exemplu, când dimensiunile nu se aliniază. Motoarele heuristic și balanced aranjează seturile; motorul max refuză un matchedSets nevid cu un 400, înainte ca un apel să fie taxat. Exporturile pdf și labelsPdf desenează membrii ca piese obișnuite, iar răspunsul avertizează în acest sens; csv, svg și dxf marchează seturile. Fără un array matchedSets nevid nu se schimbă nimic, iar parts[].id este verificat doar pe rândurile pe care le numește un set.
Mai este acceptat grainGroup?
Da. grainGroup este depreciat, dar încă acceptat și funcționează exact ca înainte: piesele care împart un grup sunt ținute pe o singură placă. Nu le-a plasat niciodată una lângă alta, deci nu dă fibră continuă între ele — pentru fronturile al căror desen trebuie să continue, folosește matchedSets. Motorul max refuză grainGroup, ca întotdeauna.

Actualizat: 13 octombrie 2026