Skip to content

Commit 3071658

Browse files
committed
Merge branch 'develop' into introduce-indexers
2 parents 76a4c17 + 55ee5ae commit 3071658

9 files changed

Lines changed: 363 additions & 235 deletions

File tree

demo/js/app.js

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const statsContainer = () => document.querySelector('.sidebar');
1212
const loadProgressive = true;
1313
let observer = null;
1414
let preview = null;
15-
let firstRender = true;
1615

1716
export const app = (window.app = createApp({
1817
setup() {
@@ -113,19 +112,20 @@ export const app = (window.app = createApp({
113112
const prevDevMode = preview.devMode;
114113
preview.clear();
115114
preview.devMode = prevDevMode;
115+
const { commands } = preview.parser.parseGCode(gcode);
116+
preview.interpreter.execute(commands, preview.job);
116117

117-
if (loadProgressive) {
118-
const { commands } = preview.parser.parseGCode(gcode);
119-
preview.interpreter.execute(commands, preview.job);
120-
if (preview.job.layers === null) {
121-
console.warn('Job is not planar');
118+
render();
119+
};
120+
121+
const render = async () => {
122+
debounce(async () => {
123+
if (loadProgressive) {
124+
await preview.renderAnimated(Math.ceil(preview.job.layers.length / 60));
125+
} else {
122126
preview.render();
123-
return;
124127
}
125-
await preview.renderAnimated(Math.ceil(preview.job.layers.length / 60));
126-
} else {
127-
preview.processGCode(gcode);
128-
}
128+
});
129129
};
130130

131131
const loadDroppedFile = async (file) => {
@@ -138,7 +138,6 @@ export const app = (window.app = createApp({
138138
};
139139

140140
const selectPreset = async (presetName) => {
141-
firstRender = true;
142141
const canvas = document.querySelector('canvas.preview');
143142
const preset = presets[presetName];
144143
fileName.value = preset.file.replace(/^.*?\//, '');
@@ -188,11 +187,7 @@ export const app = (window.app = createApp({
188187
preview.buildVolume = settings.value.drawBuildVolume ? settings.value.buildVolume : undefined;
189188
preview.backgroundColor = settings.value.backgroundColor;
190189

191-
if (!firstRender) {
192-
preview.render();
193-
} else {
194-
firstRender = false;
195-
}
190+
render();
196191
});
197192

198193
watchEffect(() => {
@@ -211,9 +206,7 @@ export const app = (window.app = createApp({
211206
preview.topLayerColor = settings.value.highlightTopLayer ? settings.value.topLayerColor : undefined;
212207
preview.lastSegmentColor = settings.value.highlightLastSegment ? settings.value.lastSegmentColor : undefined;
213208

214-
debounce(() => {
215-
preview.renderAnimated(Math.ceil(preview.job.layers.length / 60));
216-
});
209+
render();
217210
});
218211
});
219212

src/__tests__/build-volume.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { test, describe, expect, vi } from 'vitest';
2+
import { BuildVolume } from '../build-volume';
3+
import { AxesHelper } from 'three';
4+
import { Grid } from '../helpers/grid';
5+
import { LineBox } from '../helpers/line-box';
6+
7+
describe('BuildVolume', () => {
8+
test('it has a default color', () => {
9+
const buildVolume = new BuildVolume();
10+
11+
expect(buildVolume.color).toEqual(0x888888);
12+
});
13+
14+
test('it has size properties', () => {
15+
const buildVolume = new BuildVolume(10, 20, 30);
16+
17+
expect(buildVolume.x).toEqual(10);
18+
expect(buildVolume.y).toEqual(20);
19+
expect(buildVolume.z).toEqual(30);
20+
});
21+
22+
describe('.createAxes', () => {
23+
test('it creates an AxesHelper', () => {
24+
const buildVolume = new BuildVolume(10, 20, 30);
25+
26+
const axes = buildVolume.createAxes();
27+
28+
expect(axes).toBeDefined();
29+
expect(axes).toBeInstanceOf(AxesHelper);
30+
});
31+
32+
test('it scales the axes', () => {
33+
const buildVolume = new BuildVolume(10, 20, 30);
34+
35+
const axes = buildVolume.createAxes();
36+
37+
expect(axes.scale).toEqual({ x: 1, y: 1, z: -1 });
38+
});
39+
40+
test('it positions the axes', () => {
41+
const buildVolume = new BuildVolume(10, 20, 30);
42+
43+
const axes = buildVolume.createAxes();
44+
45+
expect(axes.position).toEqual({ x: -5, y: 0, z: 10 });
46+
});
47+
});
48+
49+
describe('.createGrid', () => {
50+
test('it creates a Grid', () => {
51+
const buildVolume = new BuildVolume(10, 20, 30);
52+
53+
const grid = buildVolume.createGrid();
54+
55+
expect(grid).toBeDefined();
56+
expect(grid).toBeInstanceOf(Grid);
57+
});
58+
});
59+
60+
describe('.createGroup', () => {
61+
test('it creates a group for all the objects', () => {
62+
const buildVolume = new BuildVolume(10, 20, 30);
63+
64+
const group = buildVolume.createGroup();
65+
66+
expect(group).toBeDefined();
67+
expect(group.children.length).toEqual(3);
68+
69+
expect(group.children[0]).toBeInstanceOf(LineBox);
70+
expect(group.children[1]).toBeInstanceOf(Grid);
71+
expect(group.children[2]).toBeInstanceOf(AxesHelper);
72+
});
73+
});
74+
75+
describe('.dispose', () => {
76+
test('it calls dispose on all disposables', () => {
77+
const buildVolume = new BuildVolume(10, 20, 30);
78+
79+
const axes = buildVolume.createAxes();
80+
const grid = buildVolume.createGrid();
81+
const lineBox = buildVolume.createLineBox();
82+
83+
const axesSpy = vi.spyOn(axes, 'dispose');
84+
const gridSpy = vi.spyOn(grid, 'dispose');
85+
const lineBoxSpy = vi.spyOn(lineBox, 'dispose');
86+
87+
buildVolume.dispose();
88+
89+
expect(axesSpy).toHaveBeenCalled();
90+
expect(gridSpy).toHaveBeenCalled();
91+
expect(lineBoxSpy).toHaveBeenCalled();
92+
});
93+
});
94+
});

src/build-volume.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Grid } from './helpers/grid';
2+
import { AxesHelper, Group, Vector3 } from 'three';
3+
import { LineBox } from './helpers/line-box';
4+
import { type Disposable } from './helpers/three-utils';
5+
6+
export class BuildVolume {
7+
x: number;
8+
y: number;
9+
z: number;
10+
color: number;
11+
private disposables: Disposable[] = [];
12+
13+
constructor(x: number, y: number, z: number, color: number = 0x888888) {
14+
this.x = x;
15+
this.y = y;
16+
this.z = z;
17+
this.color = color;
18+
}
19+
20+
createAxes(): AxesHelper {
21+
const axes = new AxesHelper(10);
22+
23+
const scale = new Vector3(1, 1, 1);
24+
scale.z *= -1;
25+
26+
axes.scale.multiply(scale);
27+
axes.position.setZ(this.y / 2);
28+
axes.position.setX(-this.x / 2);
29+
30+
this.disposables.push(axes);
31+
32+
return axes;
33+
}
34+
35+
createGrid(): Grid {
36+
const grid = new Grid(this.x, 10, this.y, 10, this.color);
37+
this.disposables.push(grid);
38+
return grid;
39+
}
40+
41+
createLineBox(): LineBox {
42+
const lineBox = new LineBox(this.x, this.z, this.y, this.color);
43+
this.disposables.push(lineBox);
44+
return lineBox;
45+
}
46+
47+
createGroup(): Group {
48+
const group = new Group();
49+
group.add(this.createLineBox());
50+
group.add(this.createGrid());
51+
group.add(this.createAxes());
52+
53+
return group;
54+
}
55+
56+
dispose(): void {
57+
this.disposables.forEach((disposable) => disposable.dispose());
58+
}
59+
}

src/gridHelper.ts

Lines changed: 0 additions & 79 deletions
This file was deleted.

src/helpers/grid.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { BufferGeometry, Color, Float32BufferAttribute, LineBasicMaterial, LineSegments } from 'three';
2+
3+
class Grid extends LineSegments {
4+
constructor(
5+
sizeX: number, // Size along the X axis
6+
stepX: number, // Step distance along the X axis
7+
sizeZ: number, // Size along the Z axis
8+
stepZ: number, // Step distance along the Z axis
9+
color: Color | string | number = 0x888888 // Single color for all grid lines
10+
) {
11+
// Convert color input to a Color object
12+
color = new Color(color);
13+
14+
// Calculate the number of steps along each axis
15+
const xSteps = Math.round(sizeX / stepX);
16+
const zSteps = Math.round(sizeZ / stepZ);
17+
18+
// Adjust sizes to center the grid
19+
const halfSizeX = (xSteps * stepX) / 2;
20+
const halfSizeZ = (zSteps * stepZ) / 2;
21+
22+
const vertices: number[] = [];
23+
const colors: number[] = [];
24+
let j = 0;
25+
26+
// Generate vertices and colors for lines parallel to the X-axis (moving along Z)
27+
for (let z = -halfSizeZ; z <= halfSizeZ; z += stepZ) {
28+
vertices.push(
29+
-halfSizeX,
30+
0,
31+
z, // Start point (on the X-axis)
32+
halfSizeX,
33+
0,
34+
z // End point (on the X-axis)
35+
);
36+
37+
// Assign the same color to all lines
38+
color.toArray(colors, j);
39+
j += 3;
40+
color.toArray(colors, j);
41+
j += 3;
42+
}
43+
44+
// Generate vertices and colors for lines parallel to the Z-axis (moving along X)
45+
for (let x = -halfSizeX; x <= halfSizeX; x += stepX) {
46+
vertices.push(
47+
x,
48+
0,
49+
-halfSizeZ, // Start point (on the Z-axis)
50+
x,
51+
0,
52+
halfSizeZ // End point (on the Z-axis)
53+
);
54+
55+
// Assign the same color to all lines
56+
color.toArray(colors, j);
57+
j += 3;
58+
color.toArray(colors, j);
59+
j += 3;
60+
}
61+
62+
// Create BufferGeometry and assign the vertices and colors
63+
const geometry = new BufferGeometry();
64+
geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
65+
geometry.setAttribute('color', new Float32BufferAttribute(colors, 3));
66+
67+
// Create material for the grid lines
68+
const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false });
69+
70+
// Call the parent class constructor with the geometry and material
71+
super(geometry, material);
72+
}
73+
74+
// Override the type property for clarity and identification
75+
override readonly type = 'GridHelper';
76+
77+
// Add dispose method for resource management
78+
dispose() {
79+
this.geometry.dispose();
80+
if (Array.isArray(this.material)) {
81+
this.material.forEach((material) => material.dispose());
82+
} else {
83+
this.material.dispose();
84+
}
85+
}
86+
}
87+
88+
export { Grid };

0 commit comments

Comments
 (0)