Skip to content

Commit 954c813

Browse files
authored
Bring back the tolerance logic (#224)
* Bring back the tolerance logic * Simplify the options
1 parent a017e44 commit 954c813

File tree

3 files changed

+71
-17
lines changed

3 files changed

+71
-17
lines changed

src/__tests__/job.ts

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test, expect, describe } from 'vitest';
2-
import { Job, State } from '../job';
2+
import { Job, State, LayersIndexer } from '../job';
33
import { PathType, Path } from '../path';
44

55
test('it has an initial state', () => {
@@ -96,7 +96,7 @@ describe('.layers', () => {
9696
expect(layers?.[0].length).toEqual(2);
9797
});
9898

99-
test('travel paths moving z create a new layer', () => {
99+
test('travel paths moving z above the default tolerance create a new layer', () => {
100100
const job = new Job();
101101

102102
append_path(job, PathType.Extrusion, [
@@ -105,7 +105,7 @@ describe('.layers', () => {
105105
]);
106106
append_path(job, PathType.Travel, [
107107
[5, 6, 0],
108-
[5, 6, 1]
108+
[5, 6, LayersIndexer.DEFAULT_TOLERANCE + 0.01]
109109
]);
110110

111111
const layers = job.layers;
@@ -117,6 +117,46 @@ describe('.layers', () => {
117117
expect(layers?.[1].length).toEqual(1);
118118
});
119119

120+
test('travel paths moving z under the default tolerance are on the same layer', () => {
121+
const job = new Job();
122+
123+
append_path(job, PathType.Extrusion, [
124+
[0, 0, 0],
125+
[1, 2, 0]
126+
]);
127+
append_path(job, PathType.Travel, [
128+
[5, 6, 0],
129+
[5, 6, LayersIndexer.DEFAULT_TOLERANCE - 0.01]
130+
]);
131+
132+
const layers = job.layers;
133+
134+
expect(layers).not.toBeNull();
135+
expect(layers).toBeInstanceOf(Array);
136+
expect(layers?.length).toEqual(1);
137+
expect(layers?.[0].length).toEqual(2);
138+
});
139+
140+
test('Tolerance can be set', () => {
141+
const job = new Job({ minLayerThreshold: 0.1 });
142+
143+
append_path(job, PathType.Extrusion, [
144+
[0, 0, 0],
145+
[1, 2, 0]
146+
]);
147+
append_path(job, PathType.Travel, [
148+
[5, 6, 0],
149+
[5, 6, 0.09]
150+
]);
151+
152+
const layers = job.layers;
153+
154+
expect(layers).not.toBeNull();
155+
expect(layers).toBeInstanceOf(Array);
156+
expect(layers?.length).toEqual(1);
157+
expect(layers?.[0].length).toEqual(2);
158+
});
159+
120160
test('multiple travels in a row are on the same layer', () => {
121161
const job = new Job();
122162

src/job.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ export class Job {
2424
private indexers: Indexer[];
2525
inprogressPath: Path | undefined;
2626

27-
constructor(state?: State) {
27+
constructor(opts: { state?: State; minLayerThreshold?: number } = {}) {
2828
this.paths = [];
29-
this.state = state || State.initial;
29+
this.state = opts.state || State.initial;
3030
this.layersPaths = [[]];
3131
this.indexers = [
3232
new TravelTypeIndexer({ travel: this.travelPaths, extrusion: this.extrusionPaths }),
33-
new LayersIndexer(this.layersPaths)
33+
new LayersIndexer(this.layersPaths, opts.minLayerThreshold)
3434
];
3535
}
3636

@@ -61,7 +61,7 @@ export class Job {
6161
}
6262

6363
isPlanar(): boolean {
64-
return this.paths.find((path) => path.travelType === PathType.Extrusion && path.hasVerticalMoves()) === undefined;
64+
return this.layersPaths !== null;
6565
}
6666

6767
private indexPath(path: Path): void {
@@ -84,7 +84,7 @@ export class Job {
8484
}
8585

8686
class NonApplicableIndexer extends Error {}
87-
class Indexer {
87+
export class Indexer {
8888
protected indexes: Record<string, Path[]> | Path[][];
8989
constructor(indexes: Record<string, Path[]> | Path[][]) {
9090
this.indexes = indexes;
@@ -95,7 +95,7 @@ class Indexer {
9595
}
9696
}
9797

98-
class TravelTypeIndexer extends Indexer {
98+
export class TravelTypeIndexer extends Indexer {
9999
protected declare indexes: Record<string, Path[]>;
100100
constructor(indexes: Record<string, Path[]>) {
101101
super(indexes);
@@ -115,10 +115,13 @@ class NonPlanarPathError extends NonApplicableIndexer {
115115
super("Non-planar paths can't be indexed by layer");
116116
}
117117
}
118-
class LayersIndexer extends Indexer {
118+
export class LayersIndexer extends Indexer {
119+
static readonly DEFAULT_TOLERANCE = 0.05;
119120
protected declare indexes: Path[][];
120-
constructor(indexes: Path[][]) {
121+
private tolerance: number;
122+
constructor(indexes: Path[][], tolerance: number = LayersIndexer.DEFAULT_TOLERANCE) {
121123
super(indexes);
124+
this.tolerance = tolerance;
122125
}
123126

124127
sortIn(path: Path): void {
@@ -129,10 +132,17 @@ class LayersIndexer extends Indexer {
129132
if (path.travelType === PathType.Extrusion) {
130133
this.lastLayer().push(path);
131134
} else {
132-
if (
133-
path.vertices.some((_, i, arr) => i % 3 === 2 && arr[i] !== arr[2]) &&
134-
this.lastLayer().find((p) => p.travelType === PathType.Extrusion)
135-
) {
135+
const verticalTravels = path.vertices
136+
.map((_, i, arr) => {
137+
if (i % 3 === 2 && arr[i] - arr[2] > this.tolerance) {
138+
return arr[i] - arr[2];
139+
}
140+
})
141+
.filter((z) => z !== undefined);
142+
const hasVerticalTravel = verticalTravels.length > 0;
143+
const hasExtrusions = this.lastLayer().find((p) => p.travelType === PathType.Extrusion);
144+
145+
if (hasVerticalTravel && hasExtrusions) {
136146
this.createLayer();
137147
}
138148
this.lastLayer().push(path);

src/webgl-preview.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export type GCodePreviewOptions = {
3939
lineWidth?: number;
4040
lineHeight?: number;
4141
nonTravelMoves?: string[];
42+
minLayerThreshold?: number;
4243
renderExtrusion?: boolean;
4344
renderTravel?: boolean;
4445
startLayer?: number;
@@ -61,6 +62,7 @@ export type GCodePreviewOptions = {
6162
};
6263

6364
export class WebGLPreview {
65+
minLayerThreshold: number;
6466
/**
6567
* @deprecated Please use the `canvas` param instead.
6668
*/
@@ -89,8 +91,8 @@ export class WebGLPreview {
8991
nonTravelmoves: string[] = [];
9092
disableGradient = false;
9193

94+
job: Job;
9295
interpreter = new Interpreter();
93-
job = new Job();
9496
parser = new Parser();
9597

9698
// rendering
@@ -118,6 +120,8 @@ export class WebGLPreview {
118120
private devGui?: DevGUI;
119121

120122
constructor(opts: GCodePreviewOptions) {
123+
this.minLayerThreshold = opts.minLayerThreshold ?? this.minLayerThreshold;
124+
this.job = new Job({ minLayerThreshold: this.minLayerThreshold });
121125
this.scene = new Scene();
122126
this.scene.background = this._backgroundColor;
123127
if (opts.backgroundColor !== undefined) {
@@ -366,7 +370,7 @@ export class WebGLPreview {
366370
clear(): void {
367371
this.resetState();
368372
this.parser = new Parser();
369-
this.job = new Job();
373+
this.job = new Job({ minLayerThreshold: this.minLayerThreshold });
370374
}
371375

372376
// reset processing state

0 commit comments

Comments
 (0)