diff --git a/README.md b/README.md index 1ef9fd3..15d8e8e 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,26 @@ The default is `8`. ### Travel lines You can change the line width of travel lines: ```js -renderer. travelWidth = 0.1 +renderer.travelWidth = 0.1 ``` The default is `0.01`. `0` is also possible to completely hide them. + +### Skip / Filter lines +You can skip lines when parsing the gcode based on the gcode-line: +``` +renderer.onAddLine = (newLine, lineNumber) => { + if (lineNumber > 100 && lineNumber < 30000) { + newLine.radius = 0 + return [newLine] + } + + return [newLine] +} +``` + +The return type is an array to be able to also inject additional lines if needed. +Also, as you can see in this example, you can alter the properties of the newLine. +In this case to just hide it, you can set the radius to 0. + +You can use that for example to filter for specific line-types by parsing the line types out of +the gcode in advance and then look them up in the onAddLine callback. \ No newline at end of file diff --git a/src/gcode.ts b/src/gcode.ts index f21899e..952d026 100644 --- a/src/gcode.ts +++ b/src/gcode.ts @@ -11,7 +11,7 @@ import { MeshPhongMaterial, } from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' -import { GCodeParser } from './parser' +import { GCodeParser, OnAddLineCallback } from './parser' import { SegmentColorizer } from './SegmentColorizer' /** @@ -31,6 +31,14 @@ export class GCodeRenderer { // Public configurations: + /** + * A callback which allows you to filter, modify or replace lines based on the current gcode line number. + * You have to return an array of lines. They will be used to completely replace the input line. + * + * @type (newLine: LinePoint, lineNumber: number) => LinePoint[] + */ + public onAddLine?: OnAddLineCallback + /** * Width of travel-lines. Use 0 to hide them. * @@ -188,6 +196,7 @@ export class GCodeRenderer { * Reads the GCode and renders it to a mesh. */ public async render() { + this.parser.onAddLine = this.onAddLine this.parser.parse() this.parser.getGeometries().forEach(g => { diff --git a/src/parser.ts b/src/parser.ts index d7d0476..8c6d365 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -6,6 +6,8 @@ import { LineTubeGeometry } from "./LineTubeGeometry"; import { LinePoint } from "./LinePoint"; import { SegmentColorizer, SimpleColorizer } from './SegmentColorizer'; +export type OnAddLineCallback = (newLine: LinePoint, lineNumber: number) => LinePoint[] + /** * GCode renderer which parses a GCode file and displays it using * three.js. Use .element() to retrieve the DOM canvas element. @@ -63,6 +65,14 @@ export class GCodeParser { */ public pointsPerObject: number = 120000 + /** + * A callback which allows you to filter, modify or replace lines based on the current gcode line number. + * You have to return an array of lines. They will be used to completely replace the input line. + * + * @type (newLine: LinePoint, lineNumber: number) => LinePoint[] + */ + public onAddLine?: OnAddLineCallback + /** * Creates a new GCode renderer for the given gcode. * It initializes the canvas to the given size and @@ -225,28 +235,37 @@ export class GCodeParser { let currentObject = 0 let lastAddedLinePoint: LinePoint | undefined = undefined let pointCount = 0 - const addLine = (newLine: LinePoint) => { - if (pointCount > 0 && pointCount % this.pointsPerObject == 0) { - // end the old geometry and increase the counter - this.combinedLines[currentObject].finish() - currentObject++ + const addLine = (newLine: LinePoint, lineNumber: number) => { + let lines: LinePoint[] + if (this.onAddLine) { + lines = this.onAddLine(newLine, lineNumber) + } else { + lines = [newLine] } - if (this.combinedLines[currentObject] === undefined) { - this.combinedLines[currentObject] = new LineTubeGeometry(this.radialSegments) - if (lastAddedLinePoint) { - this.combinedLines[currentObject].add(lastAddedLinePoint) + lines.forEach(line => { + if (pointCount > 0 && pointCount % this.pointsPerObject == 0) { + // end the old geometry and increase the counter + this.combinedLines[currentObject].finish() + currentObject++ } - } - - this.combinedLines[currentObject].add(newLine) - lastAddedLinePoint = newLine - pointCount++ + + if (this.combinedLines[currentObject] === undefined) { + this.combinedLines[currentObject] = new LineTubeGeometry(this.radialSegments) + if (lastAddedLinePoint) { + this.combinedLines[currentObject].add(lastAddedLinePoint) + } + } + + this.combinedLines[currentObject].add(line) + lastAddedLinePoint = line + pointCount++ + }); } // Create the geometry. //this.combinedLines[oNr] = new LineTubeGeometry(this.radialSegments) - lines.forEach((line, i)=> { + lines.forEach((line, lineNumber)=> { if (line === undefined) { return } @@ -291,7 +310,7 @@ export class GCodeParser { // As the GCode contains the extrusion for the 'current' line, // but the LinePoint contains the radius for the 'next' line // we need to combine the last point with the current radius. - addLine(new LinePoint(lastPoint.clone(), radius, color)) + addLine(new LinePoint(lastPoint.clone(), radius, color), lineNumber) // Try to figure out the layer start and end points. if (lastPoint.z !== newPoint.z) { @@ -344,7 +363,7 @@ export class GCodeParser { hotendTemp = this.parseValue(cmd.find((v) => v[0] === "S")) || 0 } - lines[i] = undefined + lines[lineNumber] = undefined }) // Finish last object