Skip to content

Commit f371ab0

Browse files
committed
feat: Add support for extra space on top and right sides of panels
1 parent 02679e1 commit f371ab0

File tree

4 files changed

+27
-13
lines changed

4 files changed

+27
-13
lines changed

npm/src/geometry.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,15 @@ export interface Point {
135135

136136
export class BoardLayouter {
137137
readonly placements: Rectangle<PartToCut>[] = [];
138+
private readonly paddedStock: Rectangle<Stock>;
138139

139140
constructor(
140141
readonly stock: Rectangle<Stock>,
141142
readonly config: Config,
142-
) {}
143+
) {
144+
const padding = -new Distance(config.extraSpace).m;
145+
this.paddedStock = stock.pad({ right: padding, top: padding });
146+
}
143147

144148
tryAddPart(part: PartToCut): boolean {
145149
if (part.material !== this.stock.data.material) return false;
@@ -161,7 +165,7 @@ export class BoardLayouter {
161165
const possiblePositions: Point[] =
162166
this.placements.length === 0
163167
? // Always position bottom left when empty
164-
[{ x: this.stock.x, y: this.stock.y }]
168+
[{ x: this.paddedStock.x, y: this.paddedStock.y }]
165169
: // Get possible locations from callback
166170
getPossiblePositions();
167171

@@ -172,7 +176,7 @@ export class BoardLayouter {
172176
)
173177
.find(
174178
(placement) =>
175-
placement.isInside(this.stock) &&
179+
placement.isInside(this.paddedStock) &&
176180
this.placements.every((p) => !placement.isIntersecting(p)),
177181
);
178182

@@ -191,9 +195,9 @@ export class BoardLayouter {
191195
const bladeWidth = new Distance(this.config.bladeWidth).m;
192196
return [
193197
// Left of stock and top of existing
194-
{ x: this.stock.x, y: existing.top + bladeWidth },
198+
{ x: this.paddedStock.x, y: existing.top + bladeWidth },
195199
// left of existing, bottom of stock
196-
{ x: existing.right + bladeWidth, y: this.stock.y },
200+
{ x: existing.right + bladeWidth, y: this.paddedStock.y },
197201

198202
// Left of existing, top of other existing
199203
...this.placements.map((existing2) => ({
@@ -262,7 +266,7 @@ export class BoardLayouter {
262266

263267
reduceStock(allStock: Rectangle<Stock>[]): BoardLayouter {
264268
const validStock = allStock.filter(
265-
(stock) => stock.data.material === this.stock.data.material,
269+
(stock) => stock.data.material === this.paddedStock.data.material,
266270
);
267271
const validLayouts = validStock
268272
.map((stock) => {

npm/src/index.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import type {
2-
PartToCut,
3-
Stock,
4-
StockMatrix,
1+
import {
2+
type PartToCut,
3+
type Stock,
4+
type StockMatrix,
55
Config,
6-
BoardLayout,
7-
BoardLayoutLeftover,
6+
type BoardLayout,
7+
type BoardLayoutLeftover,
88
} from './types';
99
import consola from 'consola';
1010
import { BoardLayouter, Rectangle } from './geometry';
@@ -26,6 +26,7 @@ export function generateBoardLayouts(
2626
layouts: BoardLayout[];
2727
leftovers: BoardLayoutLeftover[];
2828
} {
29+
config = Config.parse(config);
2930
consola.info('Generating board layouts...');
3031

3132
// Create geometry for stock and parts

npm/src/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ export const Config = z.object({
8080
* column, making it easier to cut out.
8181
*/
8282
optimize: z.union([z.literal('space'), z.literal('cuts')]).default('cuts'),
83+
/**
84+
* Extra padding to add to the top and right sides of the boards/stock.
85+
*/
86+
extraSpace: Distance.default('0'),
8387
});
8488
export type Config = z.infer<typeof Config>;
8589

npm/src/units.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,13 @@ export class Distance {
6868
this.m = Number(v.replace('ft', '')) * 0.3048;
6969
} else if (v.endsWith('in') || v.endsWith('"')) {
7070
this.m = Number(v.replace(/(in|")/, '')) * 0.0254;
71+
} else if (v.endsWith('mm')) {
72+
this.m = Number(v.replace('mm', '')) / 1000;
7173
} else {
72-
throw Error('Could not parse distance: ' + JSON.stringify(v));
74+
this.m = Number(v.replace('m', ''));
75+
}
76+
if (isNaN(this.m)) {
77+
throw Error('Could not convert to meters: ' + v);
7378
}
7479
}
7580

0 commit comments

Comments
 (0)