Skip to content

Commit ca8db3f

Browse files
committed
refactor: replace global with Number primitives
Signed-off-by: Pedro Lamas <pedrolamas@gmail.com>
1 parent 2f7e43d commit ca8db3f

File tree

9 files changed

+84
-63
lines changed

9 files changed

+84
-63
lines changed

src/components/widgets/gcode-preview/GcodePreview.vue

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
364364
@Prop({ type: Boolean })
365365
readonly disabled?: boolean
366366
367-
@Prop({ type: Number, default: Infinity })
367+
@Prop({ type: Number, default: Number.POSITIVE_INFINITY })
368368
readonly progress!: number
369369
370370
@Prop({ type: Number, default: 0 })
@@ -626,8 +626,8 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
626626
return `${x.min} ${y.min} ${x.max - x.min} ${y.max - y.min}`
627627
}
628628
629-
get defaultLayerPaths (): LayerPaths {
630-
return {
629+
get defaultLayerPaths (): Readonly<LayerPaths> {
630+
return Object.freeze({
631631
extrusions: {},
632632
moves: '',
633633
retractions: [],
@@ -637,10 +637,10 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
637637
y: 0
638638
},
639639
tool: 'T0'
640-
}
640+
})
641641
}
642642
643-
get svgPathCurrent (): LayerPaths {
643+
get svgPathCurrent (): Readonly<LayerPaths> {
644644
if (this.disabled) {
645645
return this.defaultLayerPaths
646646
}
@@ -656,23 +656,23 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
656656
return this.$typedGetters['gcodePreview/getPaths'](layer?.move ?? 0, this.progress)
657657
}
658658
659-
get svgPathActive (): LayerPaths {
659+
get svgPathActive (): Readonly<LayerPaths> {
660660
if (this.disabled) {
661661
return this.defaultLayerPaths
662662
}
663663
664664
return this.$typedGetters['gcodePreview/getLayerPaths'](this.layer)
665665
}
666666
667-
get svgPathPrevious (): LayerPaths {
667+
get svgPathPrevious (): Readonly<LayerPaths> {
668668
if (this.disabled || this.layer <= 0) {
669669
return this.defaultLayerPaths
670670
}
671671
672672
return this.$typedGetters['gcodePreview/getLayerPaths'](this.layer - 1)
673673
}
674674
675-
get svgPathNext (): LayerPaths {
675+
get svgPathNext (): Readonly<LayerPaths> {
676676
const layers: readonly Layer[] = this.$typedGetters['gcodePreview/getLayers']
677677
678678
if (this.disabled || this.layer >= layers.length) {
@@ -682,7 +682,7 @@ export default class GcodePreview extends Mixins(StateMixin, BrowserMixin) {
682682
return this.$typedGetters['gcodePreview/getLayerPaths'](this.layer + 1)
683683
}
684684
685-
get svgPathParts (): string[] {
685+
get svgPathParts (): readonly string[] {
686686
return this.$typedGetters['gcodePreview/getPartPaths']
687687
}
688688

src/store/gcodePreview/actions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const actions = {
5050
commit('setLayers', message.layers)
5151
commit('setParts', message.parts)
5252
commit('setTools', message.tools)
53+
commit('setBounds', message.bounds)
5354
commit('setParserProgress', payload.file.size ?? payload.gcode.byteLength)
5455

5556
if (rootState.config.uiSettings.gcodePreview.hideSinglePartBoundingBox && message.parts.length <= 1) {
@@ -93,6 +94,7 @@ export const actions = {
9394
commit('setLayers', [])
9495
commit('setParts', [])
9596
commit('setTools', [])
97+
commit('setBounds', null)
9698

9799
commit('setFile', payload.file)
98100

src/store/gcodePreview/getters.ts

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,6 @@ const defaultColors = ['#1fb0ff', '#ff5252', '#D67600', '#830EE3', '#B366F2', '#
88
const lightDefaultColors = ['#000', ...defaultColors]
99
const darkDefaultColors = ['#FFF', ...defaultColors]
1010

11-
const updateMinMax = (previous: { min: number, max: number }, value?: number) => {
12-
if (value != null) {
13-
previous.min = Number.isFinite(previous.min)
14-
? Math.min(previous.min, value)
15-
: value
16-
17-
previous.max = Number.isFinite(previous.max)
18-
? Math.max(previous.max, value)
19-
: value
20-
}
21-
}
22-
2311
export const getters = {
2412
getLayers: (state, getters, rootState): readonly Layer[] => {
2513
if (state.layers.length) {
@@ -73,7 +61,11 @@ export const getters = {
7361
return state.parts
7462
},
7563

76-
getBounds: (state, getters): BBox => {
64+
getBounds: (state, getters): Readonly<BBox> => {
65+
if (state.bounds != null) {
66+
return state.bounds
67+
}
68+
7769
const layers: readonly Layer[] = getters.getLayers
7870

7971
// ignore first and last layer (priming and parking)
@@ -83,34 +75,41 @@ export const getters = {
8375
? Object.freeze(state.moves.slice(moveRangeStart, moveRangeEnd))
8476
: state.moves
8577

86-
const bounds = {
78+
const bounds: BBox = {
8779
x: {
88-
min: NaN,
89-
max: NaN
80+
min: Number.POSITIVE_INFINITY,
81+
max: Number.NEGATIVE_INFINITY
9082
},
9183
y: {
92-
min: NaN,
93-
max: NaN
84+
min: Number.POSITIVE_INFINITY,
85+
max: Number.NEGATIVE_INFINITY
9486
}
9587
}
9688

9789
for (let index = 0; index < moves.length; index++) {
9890
const move = moves[index]
9991

100-
updateMinMax(bounds.x, move.x)
101-
updateMinMax(bounds.y, move.y)
92+
if (move.x != null) {
93+
bounds.x.min = Math.min(bounds.x.min, move.x)
94+
bounds.x.max = Math.max(bounds.x.max, move.x)
95+
}
96+
97+
if (move.y != null) {
98+
bounds.y.min = Math.min(bounds.y.min, move.y)
99+
bounds.y.max = Math.max(bounds.y.max, move.y)
100+
}
102101
}
103102

104-
return {
103+
return Object.freeze({
105104
x: {
106-
min: bounds.x.min || 0,
107-
max: bounds.x.max || 0
105+
min: Number.isFinite(bounds.x.min) ? bounds.x.min : 0,
106+
max: Number.isFinite(bounds.x.max) ? bounds.x.max : 0
108107
},
109108
y: {
110-
min: bounds.y.min || 0,
111-
max: bounds.y.max || 0
109+
min: Number.isFinite(bounds.y.min) ? bounds.y.min : 0,
110+
max: Number.isFinite(bounds.y.max) ? bounds.y.max : 0
112111
}
113-
}
112+
})
114113
},
115114

116115
getToolHeadPosition: (state) => (moveIndex: number): Point3D => {
@@ -121,20 +120,10 @@ export const getters = {
121120
z: NaN
122121
}
123122

124-
for (let i = moveIndex; i >= 0 && (!Number.isFinite(output.x) || !Number.isFinite(output.y) || !Number.isFinite(output.z)); i--) {
123+
for (let i = moveIndex; i >= 0 && (Number.isNaN(output.x) || Number.isNaN(output.y) || Number.isNaN(output.y)); i--) {
125124
const move = moves[i]
126125

127-
if (!Number.isFinite(output.x) && move.x != null) {
128-
output.x = move.x
129-
}
130-
131-
if (!Number.isFinite(output.y) && move.y != null) {
132-
output.y = move.y
133-
}
134-
135-
if (!Number.isFinite(output.z) && move.z != null) {
136-
output.z = move.z
137-
}
126+
Object.assign(output, move)
138127
}
139128

140129
return {
@@ -204,7 +193,7 @@ export const getters = {
204193
return tools
205194
},
206195

207-
getPaths: (state, getters) => (startMove: number, endMove: number, ignoreTools = false): LayerPaths => {
196+
getPaths: (state, getters) => (startMove: number, endMove: number, ignoreTools = false): Readonly<LayerPaths> => {
208197
const toolhead: Point3D = getters.getToolHeadPosition(startMove)
209198
const moves: readonly Move[] = state.moves
210199

@@ -265,26 +254,28 @@ export const getters = {
265254
y: toolhead.y
266255
}
267256

268-
return path
257+
return Object.freeze(path)
269258
},
270259

271-
getLayerPaths: (state, getters) => (layer: number): LayerPaths => {
260+
getLayerPaths: (state, getters) => (layer: number): Readonly<LayerPaths> => {
272261
const layers: readonly Layer[] = getters.getLayers
273262

274-
return getters.getPaths(layers[layer]?.move ?? 0, (layers[layer + 1]?.move ?? Infinity) - 1, true)
263+
return getters.getPaths(layers[layer]?.move ?? 0, (layers[layer + 1]?.move ?? Number.POSITIVE_INFINITY) - 1, true)
275264
},
276265

277-
getPartPaths: (state, getters): string[] => {
266+
getPartPaths: (state, getters): readonly string[] => {
278267
const parts: readonly Part[] = getters.getParts
279268

280-
return parts
269+
const partPaths = parts
281270
.map(part => {
282271
const polygonAsString = part.polygon
283272
.map(point => `${point.x},${point.y}`)
284273
.join('L')
285274

286275
return `M${polygonAsString}z`
287276
})
277+
278+
return Object.freeze(partPaths)
288279
},
289280

290281
getMoveIndexByFilePosition: (state) => (filePosition: number): number => {

src/store/gcodePreview/mutations.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { MutationTree } from 'vuex'
22
import { defaultState } from './state'
3-
import type { GcodePreviewState, Layer, Move, Part } from './types'
3+
import type { BBox, GcodePreviewState, Layer, Move, Part } from './types'
44
import type { AppFile, AppFileWithMeta } from '@/store/files/types'
55

66
export const mutations = {
@@ -27,6 +27,10 @@ export const mutations = {
2727
state.tools = Object.freeze(payload)
2828
},
2929

30+
setBounds (state, payload: BBox) {
31+
state.bounds = Object.freeze(payload)
32+
},
33+
3034
setFile (state, file: AppFile | AppFileWithMeta | null) {
3135
state.file = file
3236
},

src/store/gcodePreview/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const defaultState = (): GcodePreviewState => {
66
layers: [],
77
parts: [],
88
tools: [],
9+
bounds: null,
910
file: null,
1011
parserProgress: 0,
1112
parserWorker: null

src/store/gcodePreview/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export interface GcodePreviewState {
55
layers: readonly Layer[];
66
parts: readonly Part[];
77
tools: readonly number[];
8+
bounds: Readonly<BBox> | null;
89
file: AppFile | AppFileWithMeta | null;
910
parserProgress: number;
1011
parserWorker: Worker | null;

src/util/__tests__/date-time-formatters.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ describe('formatCounterSeconds', () => {
3030

3131
it('Treats invalid input as 0', () => {
3232
expect(dtf.formatCounterSeconds(NaN)).toBe('0m 0s')
33-
expect(dtf.formatCounterSeconds(Infinity)).toBe('0m 0s')
34-
expect(dtf.formatCounterSeconds(-Infinity)).toBe('0m 0s')
33+
expect(dtf.formatCounterSeconds(Number.POSITIVE_INFINITY)).toBe('0m 0s')
34+
expect(dtf.formatCounterSeconds(Number.NEGATIVE_INFINITY)).toBe('0m 0s')
3535
})
3636
})
3737

src/workers/parseGcode.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable no-fallthrough */
2-
import type { ArcMove, Layer, LinearMove, Move, Part, Point, PositioningMode } from '@/store/gcodePreview/types'
2+
import type { ArcMove, BBox, Layer, LinearMove, Move, Part, Point, PositioningMode } from '@/store/gcodePreview/types'
33
import isKeyOf from '@/util/is-key-of'
44
import { pick } from 'lodash-es'
55
import { split } from 'shlex'
@@ -81,6 +81,16 @@ const parseGcode = (gcode: string, sendProgress: (filePosition: number) => void)
8181
}
8282
let tool = 0
8383
let filePosition = 0
84+
const bounds: BBox = {
85+
x: {
86+
min: Number.POSITIVE_INFINITY,
87+
max: Number.NEGATIVE_INFINITY
88+
},
89+
y: {
90+
min: Number.POSITIVE_INFINITY,
91+
max: Number.NEGATIVE_INFINITY
92+
}
93+
}
8494

8595
// todo get from firmware
8696
// store path: printer.printer.configFile.settings.firmware_retraction
@@ -288,6 +298,13 @@ const parseGcode = (gcode: string, sendProgress: (filePosition: number) => void)
288298
toolhead.z = move.z ?? toolhead.z
289299

290300
moves.push(move)
301+
302+
if (layers.length > 0) {
303+
bounds.x.min = Math.min(bounds.x.min, toolhead.x)
304+
bounds.x.max = Math.max(bounds.x.max, toolhead.x)
305+
bounds.y.min = Math.min(bounds.y.min, toolhead.y)
306+
bounds.y.max = Math.max(bounds.y.max, toolhead.y)
307+
}
291308
}
292309
}
293310

@@ -304,6 +321,9 @@ const parseGcode = (gcode: string, sendProgress: (filePosition: number) => void)
304321
moves,
305322
layers,
306323
parts,
324+
bounds: layers.length > 0
325+
? bounds
326+
: null,
307327
tools: [...tools]
308328
.sort((a, b) => a - b)
309329
}

src/workers/parseGcode.worker.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Layer, Move, Part } from '@/store/gcodePreview/types'
1+
import type { BBox, Layer, Move, Part } from '@/store/gcodePreview/types'
22
import parseGcode from './parseGcode'
33
import { consola } from 'consola'
44

@@ -10,7 +10,8 @@ export type ParseGcodeWorkerClientMessage = {
1010
moves: Move[],
1111
layers: Layer[],
1212
parts: Part[],
13-
tools: number[]
13+
tools: number[],
14+
bounds: BBox | null
1415
} | {
1516
action: 'error',
1617
error?: unknown
@@ -30,13 +31,14 @@ const sendProgress = (filePosition: number) => {
3031
self.postMessage(message)
3132
}
3233

33-
const sendResult = (moves: Move[], layers: Layer[], parts: Part[], tools: number[]) => {
34+
const sendResult = (moves: Move[], layers: Layer[], parts: Part[], tools: number[], bounds: BBox | null) => {
3435
const message : ParseGcodeWorkerClientMessage = {
3536
action: 'result',
3637
moves,
3738
layers,
3839
parts,
39-
tools
40+
tools,
41+
bounds
4042
}
4143

4244
self.postMessage(message)
@@ -59,9 +61,9 @@ self.onmessage = (event: MessageEvent<ParseGcodeWorkerServerMessage>) => {
5961
case 'parse': {
6062
const gcode = new TextDecoder().decode(message.gcode)
6163

62-
const { moves, layers, parts, tools } = parseGcode(gcode, sendProgress)
64+
const { moves, layers, parts, tools, bounds } = parseGcode(gcode, sendProgress)
6365

64-
sendResult(moves, layers, parts, tools)
66+
sendResult(moves, layers, parts, tools, bounds)
6567

6668
break
6769
}

0 commit comments

Comments
 (0)