{"version":3,"file":"GCodeLoader.cjs","sources":["../../src/loaders/GCodeLoader.js"],"sourcesContent":["import {\n  BufferGeometry,\n  Euler,\n  FileLoader,\n  Float32BufferAttribute,\n  Group,\n  LineBasicMaterial,\n  LineSegments,\n  Loader,\n} from 'three'\n\n/**\n * GCodeLoader is used to load gcode files usually used for 3D printing or CNC applications.\n *\n * Gcode files are composed by commands used by machines to create objects.\n *\n * @class GCodeLoader\n * @param {Manager} manager Loading manager.\n */\n\nclass GCodeLoader extends Loader {\n  constructor(manager) {\n    super(manager)\n\n    this.splitLayer = false\n  }\n\n  load(url, onLoad, onProgress, onError) {\n    const scope = this\n\n    const loader = new FileLoader(scope.manager)\n    loader.setPath(scope.path)\n    loader.setRequestHeader(scope.requestHeader)\n    loader.setWithCredentials(scope.withCredentials)\n    loader.load(\n      url,\n      function (text) {\n        try {\n          onLoad(scope.parse(text))\n        } catch (e) {\n          if (onError) {\n            onError(e)\n          } else {\n            console.error(e)\n          }\n\n          scope.manager.itemError(url)\n        }\n      },\n      onProgress,\n      onError,\n    )\n  }\n\n  parse(data) {\n    let state = { x: 0, y: 0, z: 0, e: 0, f: 0, extruding: false, relative: false }\n    let layers = []\n\n    let currentLayer = undefined\n\n    const pathMaterial = new LineBasicMaterial({ color: 0xff0000 })\n    pathMaterial.name = 'path'\n\n    const extrudingMaterial = new LineBasicMaterial({ color: 0x00ff00 })\n    extrudingMaterial.name = 'extruded'\n\n    function newLayer(line) {\n      currentLayer = { vertex: [], pathVertex: [], z: line.z }\n      layers.push(currentLayer)\n    }\n\n    //Create lie segment between p1 and p2\n    function addSegment(p1, p2) {\n      if (currentLayer === undefined) {\n        newLayer(p1)\n      }\n\n      if (state.extruding) {\n        currentLayer.vertex.push(p1.x, p1.y, p1.z)\n        currentLayer.vertex.push(p2.x, p2.y, p2.z)\n      } else {\n        currentLayer.pathVertex.push(p1.x, p1.y, p1.z)\n        currentLayer.pathVertex.push(p2.x, p2.y, p2.z)\n      }\n    }\n\n    function delta(v1, v2) {\n      return state.relative ? v2 : v2 - v1\n    }\n\n    function absolute(v1, v2) {\n      return state.relative ? v1 + v2 : v2\n    }\n\n    let lines = data.replace(/;.+/g, '').split('\\n')\n\n    for (let i = 0; i < lines.length; i++) {\n      let tokens = lines[i].split(' ')\n      let cmd = tokens[0].toUpperCase()\n\n      //Argumments\n      let args = {}\n      tokens.splice(1).forEach(function (token) {\n        if (token[0] !== undefined) {\n          let key = token[0].toLowerCase()\n          let value = parseFloat(token.substring(1))\n          args[key] = value\n        }\n      })\n\n      //Process commands\n      //G0/G1 – Linear Movement\n      if (cmd === 'G0' || cmd === 'G1') {\n        let line = {\n          x: args.x !== undefined ? absolute(state.x, args.x) : state.x,\n          y: args.y !== undefined ? absolute(state.y, args.y) : state.y,\n          z: args.z !== undefined ? absolute(state.z, args.z) : state.z,\n          e: args.e !== undefined ? absolute(state.e, args.e) : state.e,\n          f: args.f !== undefined ? absolute(state.f, args.f) : state.f,\n        }\n\n        //Layer change detection is or made by watching Z, it's made by watching when we extrude at a new Z position\n        if (delta(state.e, line.e) > 0) {\n          line.extruding = delta(state.e, line.e) > 0\n\n          if (currentLayer == undefined || line.z != currentLayer.z) {\n            newLayer(line)\n          }\n        }\n\n        addSegment(state, line)\n        state = line\n      } else if (cmd === 'G2' || cmd === 'G3') {\n        //G2/G3 - Arc Movement ( G2 clock wise and G3 counter clock wise )\n        //console.warn( 'THREE.GCodeLoader: Arc command not supported' );\n      } else if (cmd === 'G90') {\n        //G90: Set to Absolute Positioning\n        state.relative = false\n      } else if (cmd === 'G91') {\n        //G91: Set to state.relative Positioning\n        state.relative = true\n      } else if (cmd === 'G92') {\n        //G92: Set Position\n        let line = state\n        line.x = args.x !== undefined ? args.x : line.x\n        line.y = args.y !== undefined ? args.y : line.y\n        line.z = args.z !== undefined ? args.z : line.z\n        line.e = args.e !== undefined ? args.e : line.e\n        state = line\n      } else {\n        //console.warn( 'THREE.GCodeLoader: Command not supported:' + cmd );\n      }\n    }\n\n    function addObject(vertex, extruding, i) {\n      let geometry = new BufferGeometry()\n      geometry.setAttribute('position', new Float32BufferAttribute(vertex, 3))\n      let segments = new LineSegments(geometry, extruding ? extrudingMaterial : pathMaterial)\n      segments.name = 'layer' + i\n      object.add(segments)\n    }\n\n    const object = new Group()\n    object.name = 'gcode'\n\n    if (this.splitLayer) {\n      for (let i = 0; i < layers.length; i++) {\n        let layer = layers[i]\n        addObject(layer.vertex, true, i)\n        addObject(layer.pathVertex, false, i)\n      }\n    } else {\n      const vertex = [],\n        pathVertex = []\n\n      for (let i = 0; i < layers.length; i++) {\n        let layer = layers[i]\n        let layerVertex = layer.vertex\n        let layerPathVertex = layer.pathVertex\n\n        for (let j = 0; j < layerVertex.length; j++) {\n          vertex.push(layerVertex[j])\n        }\n\n        for (let j = 0; j < layerPathVertex.length; j++) {\n          pathVertex.push(layerPathVertex[j])\n        }\n      }\n\n      addObject(vertex, true, layers.length)\n      addObject(pathVertex, false, layers.length)\n    }\n\n    object.quaternion.setFromEuler(new Euler(-Math.PI / 2, 0, 0))\n\n    return object\n  }\n}\n\nexport { GCodeLoader }\n"],"names":["Loader","FileLoader","LineBasicMaterial","BufferGeometry","Float32BufferAttribute","LineSegments","Group","Euler"],"mappings":"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"}