Dokumentacja API
Optymalizator jako usługa HTTP: wyślij listę cięć i materiał, odbierz gotowy plan cięcia lub PDF do druku. Stabilny, wersjonowany i kompatybilny wstecz: pola są dodawane, nigdy usuwane.
Wprowadzenie
Bazowy URL: https://api.linearcutting.com. Wszystko jest w formacie JSON, oprócz punktu końcowego PDF. Zapytania są bezstanowe: nie przechowujemy twoich list cięć.
Nie potrzebujesz klucza API, żeby to wypróbować. Poniższa komenda zadziała od razu. Wklej ją do terminala.
curl -X POST https://api.linearcutting.com/v1/optimise \
-H "Content-Type: application/json" \
-d '{"parts": "2400x5, 1800x3", "stock": 6000}' To jest cała lista cięć: pięć elementów po 2400, trzy po 1800, do wycięcia ze sztang 6000mm. W odpowiedzi otrzymasz rozkłady, wymaganą liczbę sztang, ilość odpadu oraz informację, czy plan jest dowodliwie optymalny.
Nieuwierzytelnione wywołania API działają w planie darmowym. Pozwala to przetestować usługę przed zakupem. Obowiązuje limit na adres IP: 30 zapytań na godzinę i 250 miesięcznie. Po jego przekroczeniu API zwraca błąd 429 z informacją o terminie resetu. Nieudane wywołania nie wliczają się do limitu. Do zastosowań produkcyjnych kup klucz (od 5$ miesięcznie). Zwiększa on limity zapytań i rozmiarów oraz zapewnia osobną pulę zasobów, więc duży ruch w planie darmowym nie wpływa na Twoje operacje.
Oficjalni klienci
Zero zależności, licencja MIT i nie wymagają klucza. Jeśli pracujesz w Pythonie lub JavaScripcie, nie pisz ręcznie fetch:
import linearcutting as lc
plan = lc.optimise(parts="2400x5, 1800x3", stock=6000)
plan.bars_used # 4
plan.optimal # True, proved, not guessed 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 · Kod źródłowy Pythona · Kod źródłowy JavaScript
Dwie solidne gwarancje. verified ma zawsze wartość true przy powodzeniu: każdy plan jest ponownie sprawdzany względem danych wejściowych przed odesłaniem, więc wadliwy plan nigdy do Ciebie nie dotrze. optimal to dowód, a nie przypuszczenie. Wartość jest true tylko wtedy, gdy algorytm ustalił, że nie istnieje lepszy plan, albo przez wyczerpanie możliwości, albo przez certyfikat. Gdy nie da się tego udowodnić w dostępnym czasie, zwracamy false, zamiast zgadywać.
optimal i stockBarsLowerBound to dwie różne wartości, które celowo mogą być niezgodne. Dolny próg to wartość przybliżona, w uproszczeniu „suma długości ÷ długość sztangi” i często jest nieosiągalny. Pięć sztuk 2400 i trzy 1800 to 17 400 mm, czyli 2,9 sztangi o dł. 6000, więc próg wyniesie 3. W rzeczywistości nie da się wyciąć tych elementów z 3 sztang; prawdziwe minimum to 4 i dowodzi tego algorytm. Zatem stockBarsUsed: 4 przy stockBarsLowerBound: 3 i optimal: true nie jest sprzecznością. Oznacza to, że próg był niedokładny, a nie, że plan był zły. Użyj optimal, by decydować, czy kontynuować obliczenia. Próg traktuj tylko jako kontrolę poprawności.
Zapis skrócony
Forma długa jest szczegółowa i trochę rozwlekła. W typowym przypadku użyj skróconej: liczba oznacza długość, a x oznacza liczbę sztuk:
{"parts": "2400x5, 1800x3, 600", "stock": 6000} Każdy z poniższych zapisów oznacza to samo, więc użyj tego, który najlepiej pasuje do Twojego kodu:
{"parts": "2400x5"}
{"parts": ["2400x5"]}
{"parts": [[2400, 5]]}
{"parts": [{"length": 2400, "quantity": 5}]} Trzeci element to etykieta dla części i cena dla materiału: [2400, 5, "szyna"], [6000, 20, 45.50]. stock to nowa, wygodniejsza nazwa dla dawnego podziału na stockLength / stocks. Sama liczba oznacza „ta długość, kup ile potrzebujesz”.
Zapis skrócony jest rozwijany przed innymi operacjami, więc jest to tylko inny sposób zapisu, a nie osobny tryb: krótkie zapytanie i jego rozwinięta, długa forma zwrócą identyczne plany cięcia. Można je dowolnie mieszać. Wszystkie dotychczasowe zapytania działają tak samo jak wcześniej.
Lista cięć w adresie URL
Małe zadania mieszczą się w zapytaniu, więc można użyć metody GET. To przydatne do udostępniania linków, wycen lub zgłaszania błędów:
curl "https://api.linearcutting.com/v1/optimise?parts=2400x5,1800x3&stock=6000" Te same dane uwierzytelniające, te same limity i ten sam plan co dla POST. Można otworzyć w przeglądarce.
Uwierzytelnianie
Plan publiczny nie wymaga klucza. W planach płatnych klucz przesyłany jest w nagłówku; klucze zawierają też dozwolone domeny, więc zapytania z własnej strony działają bez serwera proxy.
X-API-Key: lk_live_9f2c... Nieprawidłowy lub nieważny klucz zwraca błąd 401. Klucze są wydawane dla obszaru roboczego: zobacz plany.
POST /v1/optimise
Optymalizuje listę cięć. Zwraca plan, statystyki i gwarantowane granice.
Treść zapytania
| Field | Typ | Domyślnie | Opis |
|---|---|---|---|
parts wymagane | tablica | - | Elementy do wycięcia. Każdy: length (> 0), quantity (int ≥ 1), opcjonalnie label, material, leftAngle, rightAngle. |
stockLength | liczba | - | Pojedyncza długość materiału w nieograniczonej ilości. Użyj tego lub stocks, nie obu. |
stocks | tablica | - | Długości handlowe. Każda: length, quantity (null = bez limitu), price (null = optymalizuj pod kątem materiału, nie kosztu), opcjonalnie material, priority. |
offcuts | tablica | [] | Odcinki, które już masz: length, quantity, opcjonalnie material, priority. Materiał darmowy, nie wliczany do zakupów. |
kerf | liczba ≥ 0 | 0 | Szerokość rzazu. |
trim | logiczny | false | Przytnij oba końce każdej sztangi materiału przed cięciem. |
method | ciąg znaków | balanced | balanced, least_waste, offcuts_first, fewest_setups (alias: fewest_setups). Podanie cen w stocks przełącza tryb balanced na optymalizację wg najniższego kosztu. |
minRemnant | liczba ≥ 0 | 0 | Odcinki o tej długości lub dłuższe wracają jako usableRemnants, a nie odpad. |
angleCuts | obiekt | wyłączone | {enabled, width, axialSymmetry}. Zobacz cięcia pod kątem. |
unit | ciąg znaków | "mm" | Zwracane w odpowiedzi i drukowane na PDF. Nic nie jest przeliczane. |
unitFormat | ciąg znaków | decimal | fraction renderuje wymiary na PDF jako ułamki z dokładnością do 1/64. |
timeLimit | sekundy | auto | Limit czasu na obliczenia, ograniczony przez plan. Wyszukiwanie jest typu 'anytime': dłuższy limit może tylko polepszyć wynik. |
Odpowiedź
{
"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" }
} | Field | Opis |
|---|---|
plan.combinations[] | Jeden wpis na każdy odrębny rozkład. usedComb.combination zawiera listę elementów ciętych z danej sztangi, length to jej długość, source to stock lub offcut, a count to liczba sztang do pocięcia w ten sposób. |
usedComb.waste | total = materiał − elementy; z podziałem na saw (rzaz + naddatek) i remnant (końcówka). |
plan.purchases[] | Lista zakupów: length, count, oraz price/cost, jeśli podano ceny. |
plan.usableRemnants | Końcówki ≥ minRemnant, od największej: materiał na przyszłe zlecenia. |
plan.unusedOffcuts | Odpady użytkowe, których plan nie wykorzystał. |
plan.stockBarsUsed | Całkowita liczba sztang do zakupu. |
plan.optimal | Dowód. Prawda tylko wtedy, gdy plan osiągnął dowodliwe minimum (lub gdy poszukiwanie zostało zakończone). Można bezpiecznie pokazać użytkownikom jako „najlepszy możliwy”. |
plan.verified | Zawsze prawda w przypadku sukcesu: zapotrzebowanie zaspokojone, każdy rozkład fizycznie możliwy, dostępność odpadów użytkowych zachowana. |
plan.stockBarsLowerBound, costLowerBound | Dowodliwe minima. Gdy optimal jest fałszem, różnica pokazuje, jak bardzo plan może odbiegać od optimum. |
stats | Podsumowanie zlecenia: elementy, długości, yieldPercent, cutCount, layoutCount, totalCost, trueWaste, oraz byMaterial w przypadku użycia grup materiałowych. |
POST /v1/optimise/pdf
To samo ciało żądania, plus opcjonalne jobName. Zwraca application/pdf: strona 1 to podsumowanie dla menedżera (zamówienie, koszty, certyfikat optymalności); kolejne strony to arkusze dla operatora piły z pozycjami cięć, etykietami elementów i polem wyboru dla każdej sztangi. Użytkownicy z kluczem otrzymują wydruk z własnym logo lub nazwą.
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
{ "status": "ok", "version": "1.3.0", "solver": "Linear Cutlist Optimizer v2" } Grupy materiałowe
Oznacz parts, stocks i offcuts za pomocą material, a każdy materiał zostanie zoptymalizowany jako osobne zadanie w ramach jednego zapytania: cięcia są wykonywane tylko na materiale tego samego rodzaju. Plany rozkroju i zakupy wracają z tagami, a stats.byMaterial przedstawia wyniki dla każdej grupy.
{
"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 dla sztangi lub odrzynka jest miękkim priorytetem: spośród tak samo dobrych planów, elementy z priorytetem zostaną użyte w pierwszej kolejności. Nigdy nie odbywa się to kosztem jakości planu.
Cięcia pod kątem
Nadaj częściom leftAngle i rightAngle i włącz angleCuts. Kąty to kąty dolne leżącego elementu; kąt górny wprowadź jako liczbę ujemną (120 i -60 to to samo cięcie). Prawidłowy zakres po przekształceniu: 10 do 170 stopni.
| angleCuts field | Opis |
|---|---|
enabled | Główny przełącznik. Kąty na częściach są akceptowane tylko, gdy ma wartość true. |
width | Szerokość materiału, w tej samej jednostce co długości. Cięcie pod kątem sięga na bok o width / tan(angle). |
axialSymmetry | none, X, Y, Z lub XYZ: określa dozwolone obroty materiału, co decyduje o zagnieżdżaniu cięć ukośnych. Profil kwadratowy to typowo XYZ; materiał jednostronny to none. |
Gdy dwa sąsiednie cięcia ukośne są równoległe, jedno cięcie piłą tworzy obie krawędzie. Plany rozkroju w trybie kątowym dodają uporządkowaną tablicę parts (z użytą orientacją) i cutPositions: każde cięcie mierzone od początku sztangi, jako para [góra, dół], gdy jest pod kątem, lub jako pojedyncza liczba, gdy jest proste.
"cutPositions": [[1200, 1300], [2442.265, 2500], 3300] Błędy
Treść błędu ma postać { "error": "...", "detail": "..." }. Pole detail jest przeznaczone dla człowieka: wskazuje część lub materiał powodujący błąd.
| Status | Błąd | Kiedy |
|---|---|---|
| 400 | validation | Błędne długości lub ilości, nieznana metoda, część niepasująca do żadnego materiału, zapotrzebowanie przekraczające dostępny materiał, naruszone zasady cięć kątowych, wysłano jednocześnie stocks i stockLength. |
| 401 | badKey | Brakujący, nieznany lub wyłączony klucz API. |
| 413 | partsLimit | Więcej części niż pozwala na to Twój plan taryfowy. |
| 429 | rateLimited | Osiągnięto limit zapytań lub limit miesięczny. Zastosuj się do nagłówka Retry-After. |
| 503 | busy | Solver jest obciążony. Spróbuj ponownie za chwilę. |
Limity zapytań
Limity ograniczają, nigdy nie generują dodatkowych opłat. Zapytania, które nie przejdą walidacji, nie są wliczane do limitu miesięcznego. Szczegóły na stronie planów taryfowych.
| Guard | Darmowy | Płatne plany |
|---|---|---|
| Limit | 10 zapytań / 5 min na adres IP | 20-240 / min zależnie od planu |
| Całkowita liczba elementów | 300 | 500 - 5,000 |
| Liczba unikalnych pozycji | 60 | do 400 |
| Budżet na obliczenia | 20 s | 60 - 300 s |
Limit obejmuje zarówno pozycje na liście, jak i łączną liczbę elementów, ponieważ koszt obliczeń zależy od zróżnicowania długości: 300 identycznych cięć daje optymalny wynik w milisekundy, 300 różnych nie.
Przykłady
Najtańszy miks z kilku długości materiału (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 Elementy ramy cięte pod kątem (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"]) Obsługa dużych, czasochłonnych zadań
Duże listy mogą być przetwarzane od kilku sekund do kilku minut. Wyszukiwanie można przerwać w dowolnym momencie, więc ustaw timeLimit na wartość akceptowalną dla Twojego interfejsu i użyj optimal, aby poinformować użytkowników, czy wynik jest ostateczny, czy tylko najlepszy z dotychczas znalezionych.
{ "parts": [ /* 900 parts */ ], "stockLength": 6500,
"kerf": 4, "timeLimit": 60 }