Dokumentace API

Optimalizační software jako HTTP služba: pošlete seznam dílů a materiálu, obdržíte ověřený nářezový plán nebo PDF k tisku. Stabilní, s verzováním a zpětně kompatibilní: pole se pouze přidávají, nikdy neodebírají.

Úvod

Základní URL https://api.linearcutting.com. Vše je ve formátu JSON, kromě koncového bodu pro PDF. Požadavky jsou bezstavové: vaše nářezové listy neukládáme.

K vyzkoušení nepotřebujete API klíč. Následující řádek funguje tak, jak je napsaný. Vložte ho do terminálu.

Copy, paste, run
curl -X POST https://api.linearcutting.com/v1/optimise \
  -H "Content-Type: application/json" \
  -d '{"parts": "2400x5, 1800x3", "stock": 6000}'

Toto je kompletní nářezový list: pět dílů po 2400, tři po 1800, řezáno z tyčí 6000mm. Získáte rozvržení, počet potřebných tyčí, množství odpadu a informaci, zda je plán prokazatelně optimální.

Volání bez klíče běží na veřejné vrstvě zdarma. Můžete si všechno vyzkoušet, než zaplatíte: 30 požadavků za hodinu a 250 za měsíc na jednu IP adresu. Po překročení limitu dostanete chybu 429 s časem, kdy se limit obnoví. Neúspěšná volání se do limitu nepočítají. Pro skutečnou práci si pořiďte klíč od $5 měsíčně. Zruší oba limity, navýší stropy pro velikost úlohy a dá vám vlastní souběžnost, takže vás odpolední špička na veřejné vrstvě nebude zpomalovat.

Oficiální klienti

Nulové závislosti, licence MIT a také nepotřebují žádný klíč. Pokud pracujete v Pythonu nebo JavaScriptu, nepište si fetch ručně:

pip install linearcutting
import linearcutting as lc

plan = lc.optimise(parts="2400x5, 1800x3", stock=6000)
plan.bars_used   # 4
plan.optimal     # True, proved, not guessed
npm install linearcutting
import { optimise } from "linearcutting";

const plan = await optimise({ parts: "2400x5, 1800x3", stock: 6000 });
plan.barsUsed;   // 4
plan.optimal;    // true

Python na PyPI · JavaScript na npm · Zdrojový kód pro Python · Zdrojový kód pro JavaScript

Dvě záruky, o které se můžete opřít. verified je při úspěchu vždycky true: každý plán před vrácením znovu kontrolujeme podle vašich vstupů, takže se k vám nemůže dostat plán, který by ve skutečnosti nenaplnil váš seznam dílů. optimal je důkaz, ne odhad. Je true, jen když hledání prokáže, že žádný lepší plán neexistuje, a to buď vyčerpáním všech možností, nebo certifikátem. Když to nelze v daném časovém limitu dokázat, raději řekneme false, než abychom doufali.

optimal a stockBarsLowerBound jsou dvě různé věci a neshodují se záměrně. Dolní mez je zjednodušení, zhruba "celková délka ÷ délka tyče", a často není dosažitelná. Pět kusů po 2400 a tři po 1800 je 17 400 mm, což je 2,9 tyče o délce 6000, takže mez je 3. Tyto díly ale ze 3 tyčí nenařežete; 4 jsou skutečné minimum a optimalizátor to dokáže. Takže stockBarsUsed: 4 s stockBarsLowerBound: 3 a optimal: true není rozpor. Znamená to, že mez byla volná, ne že plán byl špatný. Podle optimal se rozhodněte, zda pokračovat v hledání; mez použijte jen pro zběžnou kontrolu.

Zkrácený zápis

Plný zápis je explicitní a trochu zdlouhavý. Pro běžné případy použijte zkratku: číslo je délka a x znamená počet kusů:

The short form
{"parts": "2400x5, 1800x3, 600", "stock": 6000}

Všechny zápisy znamenají totéž. Použijte ten, který se vám nejvíc hodí do kódu:

All equivalent
{"parts": "2400x5"}
{"parts": ["2400x5"]}
{"parts": [[2400, 5]]}
{"parts": [{"length": 2400, "quantity": 5}]}

Třetí prvek je štítek pro díl a cena pro materiál: [2400, 5, "rail"], [6000, 20, 45.50]. A stock je přívětivější název pro staré rozdělení stockLength / stocks. Samotné číslo znamená "tato délka, pořiďte, kolik potřebujete".

Zkratka se rozbalí před vším ostatním, takže je to způsob zápisu, ne jiný režim: krátký požadavek a dlouhý požadavek, na který se rozbalí, vracejí bajtově identické plány. Kombinujte je libovolně, každý stávající požadavek stále funguje přesně jako dřív.

Seznam dílů v URL

Malé úlohy se vejdou do URL, takže funguje i GET. Hodí se to pro odkaz, který chcete sdílet, poslat v nabídce nebo v hlášení o chybě:

GET /v1/optimise
curl "https://api.linearcutting.com/v1/optimise?parts=2400x5,1800x3&stock=6000"

Stejné ověření, stejné limity, stejný plán jako u POST. Můžete si ho otevřít v prohlížeči.

Ověření

Veřejný tarif klíč nepotřebuje. Placené tarify posílají klíč v hlavičce; klíče také obsahují povolené domény pro prohlížeče, takže volání z vašich stránek fungují bez proxy.

http
X-API-Key: lk_live_9f2c...

Špatný nebo propadlý klíč vrátí 401. Klíče se vydávají pro pracovní prostor: viz tarify.

POST /v1/optimise

Vyřeší seznam dílů. Vrátí plán, statistiky a prokazatelné meze.

Tělo požadavku

FieldTypVýchozíPopis
parts vyžadováno pole- Díly, které potřebujete. Každý: length (> 0), quantity (celé číslo ≥ 1), volitelně label, material, leftAngle, rightAngle.
stockLength číslo- Jedna skladová délka v neomezeném množství. Použijte toto nebo stocks, ne obojí.
stocks pole- Nakupované délky. Každá: length, quantity (null = neomezeně), price (null = optimalizovat materiál místo peněz), volitelně material, priority.
offcuts pole[] Délky, které již máte: length, quantity, volitelně material, priority. Materiál zdarma, nikdy se nepočítá jako nákup.
kerfčíslo ≥ 00Šířka prořezu při každém řezu.
trimlogická hodnotafalseProvede jeden začišťovací řez na obou koncích každého kusu materiálu.
methodřetězecbalanced balanced, least_waste, offcuts_first, fewest_setups (alias: fewest_setups). Ceny v poli stocks přepnou metodu balanced na nejnižší cenu.
minRemnantčíslo ≥ 00Zbytky této délky nebo delší se vrací jako usableRemnants namísto odpadu.
angleCutsobjektvypnuto{enabled, width, axialSymmetry}. Viz úhlové řezy.
unitřetězec"mm"Vrátí se v odpovědi a tiskne se na PDF. Nic nepřevádí.
unitFormatřetězecdesetinnéHodnota fraction vykreslí rozměry v PDF jako zlomky s přesností na 1/64.
timeLimitsekundyautoČas na výpočet, omezený tarifem. Hledání je typu „anytime“: delší čas výsledek pouze vylepší.

Odpověď

200 application/json
{
  "plan": {
    "combinations": [
      {
        "usedComb": {
          "combination": [2400, 2400, 1200],
          "length": 6500,
          "source": "stock",
          "waste": { "total": 492, "remnant": 484, "saw": 8 }
        },
        "count": 2
      }
    ],
    "purchases":      [{ "length": 6500, "count": 2 }],
    "usableRemnants": [],
    "unusedOffcuts":  [],
    "stockBarsUsed":  2,
    "stockBarsLowerBound": 2,
    "totalWaste":     984,
    "optimal":        true,
    "verified":       true,
    "solveTimeMs":    12.5
  },
  "stats": {
    "totalParts": 8, "totalPartsLength": 15600, "totalUsedLength": 16600,
    "yieldPercent": 93.98, "cutCount": 8, "layoutCount": 1,
    "totalCost": null, "trueWaste": 984
  },
  "costLowerBound": null,
  "meta": { "method": "balanced", "kerf": 4, "tier": "public",
            "poweredBy": "linearcutting.com" }
}
FieldPopis
plan.combinations[]Jeden záznam pro každé rozvržení. usedComb.combination uvádí díly řezané z dané tyče, length je zdroj, source je stock (materiál) nebo offcut (odřezek) a count je počet tyčí k řezání tímto způsobem.
usedComb.wastetotal = zdroj − díly; rozděleno na saw (prořez + ořez) a remnant (zbytek).
plan.purchases[]Nákupní seznam: length (délka), count (počet) a price/cost (cena/náklady), pokud jste zadali ceny.
plan.usableRemnantsZbytky ≥ minRemnant, od největšího: materiál z odřezků pro příští použití.
plan.unusedOffcutsOdřezky, které plán nepotřeboval.
plan.stockBarsUsedCelkem tyčí k nákupu.
plan.optimalDůkaz. Pravda pouze v případě, že plán dosáhl prokazatelného minima (nebo bylo hledání vyčerpávající). Lze bezpečně zobrazit uživatelům jako „nejlepší možný“.
plan.verifiedVždy pravda při úspěchu: poptávka uspokojena, každé rozvržení fyzicky sedí, zásoba odřezků respektována.
plan.stockBarsLowerBound, costLowerBoundProkazatelná minima. Když je optimal nepravda, rozdíl udává, o kolik se plán může maximálně lišit.
statsSouhrny zakázky: díly, délky, yieldPercent (využití v %), cutCount (počet řezů), layoutCount (počet rozvržení), totalCost (celkové náklady), trueWaste (skutečný odpad) a byMaterial při použití skupin materiálu.

POST /v1/optimise/pdf

Stejné tělo požadavku plus volitelný jobName (název zakázky). Vrací application/pdf: strana 1 je souhrn pro vedoucího projektu (nákupní objednávka, náklady, certifikát optimality); další strany jsou listy pro operátora pily s průběžnými pozicemi řezu, štítky dílů a zaškrtávacím políčkem pro každou tyč. Volajícím s klíčem se vykreslí jejich značka nebo atribuce.

bash
curl -X POST https://api.linearcutting.com/v1/optimise/pdf \
  -H "Content-Type: application/json" \
  -H "X-API-Key: lk_live_9f2c..." \
  -d '{ "parts": [{"length": 2400, "quantity": 4}], "stockLength": 6500,
       "kerf": 4, "jobName": "Smith deck order" }' \
  --output cutting-plan.pdf

GET /v1/health

json
{ "status": "ok", "version": "1.3.0", "solver": "Linear Cutlist Optimizer v2" }

Skupiny materiálu

Označte parts, stocks a offcuts pomocí material a každý materiál se řeší jako samostatná úloha v rámci jednoho požadavku: řezy se provádějí pouze na materiálu stejného typu. Nářezové plány a nákupy se vrací označené a stats.byMaterial rozděluje čísla podle skupin.

json
{
  "parts": [
    { "length": 2400, "quantity": 4, "material": "40x40 SHS" },
    { "length": 1300, "quantity": 6, "material": "Pine 90x45" }
  ],
  "stocks": [
    { "length": 6500, "quantity": null, "material": "40x40 SHS" },
    { "length": 5400, "quantity": null, "material": "Pine 90x45", "priority": true }
  ],
  "kerf": 3
}

priority: true u skladového materiálu nebo zbytku je mírná preference: mezi stejně dobrými plány se upřednostněné položky použijí jako první. Nikdy to není na úkor kvality plánu.

Úhlové / pokosové řezy

Zadejte u dílů leftAngle a rightAngle a povolte angleCuts. Úhly jsou spodní úhly dílu v poloze ležmo; horní úhel zadejte jako záporné číslo (120 a -60 je stejný řez). Platný rozsah po této transformaci: 10 až 170 stupňů.

angleCuts fieldPopis
enabledHlavní vypínač. Úhly u dílů se přijímají, pouze pokud je nastaveno na true.
widthŠířka materiálu, stejná jednotka jako délky. Úhlový řez zasahuje do strany o width / tan(angle).
axialSymmetrynone, X, Y, Z nebo XYZ: které překlopení materiál umožňuje, což rozhoduje o tom, jak se mohou pokosy vnořovat. Čtvercová trubka je typicky XYZ; jednostranný materiál je none.

Pokud jsou dva sousední pokosy rovnoběžné, jeden řez pilou vytvoří obě hrany. Nářezové plány v úhlovém režimu přidávají seřazené pole parts (s použitou orientací) a cutPositions: každý řez měřený od nulového konce tyče, jako dvojice [nahoře, dole], pokud je pod úhlem, nebo jako jedno číslo, pokud je kolmý.

angle-mode layout (excerpt)
"cutPositions": [[1200, 1300], [2442.265, 2500], 3300]

Chyby

Těla chybových hlášení jsou { "error": "...", "detail": "..." }. Pole detail je napsáno tak, aby se zobrazilo člověku: pojmenovává problematický díl nebo materiál.

StatusChybaKdy
400validationŠpatné délky nebo množství, neznámá metoda, díl, který se nevejde do žádného zdroje, poptávka převyšuje omezené zásoby, porušení pravidel pro úhly, odesláno současně stocks i stockLength.
401badKeyChybějící, neznámý nebo deaktivovaný klíč API.
413partsLimitVíce dílů, než váš tarif povoluje.
429rateLimitedDosažen rychlostní nebo měsíční limit. Respektujte Retry-After.
503busyŘešitel je vytížen. Zkuste to za chvíli znovu.

Rychlostní limity

Limity omezují, nikdy negenerují účty za překročení. Požadavky, které selžou při validaci, se nezapočítávají do vašeho měsíčního limitu. Úplná čísla jsou na stránce s tarify.

GuardZdarmaPlacené tarify
Limit10 požadavků / 5 min na IP20-240 / min podle tarifu
Celkem dílů300500 - 5,000
Různých položek dílů60až 400
Výpočetní čas20 s60 - 300 s

Limit platí pro různé položky dílů i pro celkový počet dílů, protože složitost výpočtu závisí na rozmanitosti délek: 300 stejných řezů se spočítá za milisekundy, 300 různých ne.

Příklady

Nejlevnější kombinace z několika skladových délek (JavaScript)

javascript
const res = await fetch("https://api.linearcutting.com/v1/optimise", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": "lk_live_9f2c...",
  },
  body: JSON.stringify({
    parts: [
      { length: 3000, quantity: 8 },
      { length: 1200, quantity: 10 },
    ],
    stocks: [
      { length: 6500, quantity: null, price: 45 },   // unlimited
      { length: 12000, quantity: 4, price: 70 },     // only four on hand
    ],
    offcuts: [{ length: 2600, quantity: 1 }],
    kerf: 4,
    minRemnant: 400,
    method: "balanced",   // prices present -> optimises dollars
  }),
});

const { plan, stats } = await res.json();
console.log(plan.purchases);     // what to buy
console.log(stats.totalCost);    // what it costs
console.log(plan.optimal);       // true = provably the cheapest

Díly rámu s pokosovými řezy (Python)

python
import requests

r = requests.post(
    "https://api.linearcutting.com/v1/optimise",
    json={
        "parts": [
            {"length": 1300, "quantity": 2, "leftAngle": 90, "rightAngle": 45},
            {"length": 1200, "quantity": 2, "leftAngle": 135, "rightAngle": 60},
        ],
        "stockLength": 3310,
        "kerf": 0,
        "angleCuts": {"enabled": True, "width": 100, "axialSymmetry": "none"},
    },
    timeout=30,
)
r.raise_for_status()

for combo in r.json()["plan"]["combinations"]:
    print(combo["count"], "x", combo["usedComb"]["cutPositions"])

Zpracování pomalé, velké úlohy

Velké seznamy mohou trvat sekundy až minuty. Výpočet lze kdykoli přerušit, takže nastavte timeLimit na dobu, po kterou vaše UI může čekat, a zobrazte optimal, aby uživatelé věděli, jestli je výsledek ověřený, nebo jen nejlepší dosud nalezený.

json
{ "parts": [ /* 900 parts */ ], "stockLength": 6500,
  "kerf": 4, "timeLimit": 60 }