From f5353af21f28c133013c6ef0c1a05dbb86feeadf Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 20 May 2026 09:50:05 +0000 Subject: [PATCH] fix: enable and improve tool diameter simulation - Uncomment simulation UI in index.html - Fix toolDiameter input range - Update parseGcode to store toolpath segments - Rewrite bt_simulate for accuracy and performance using CurvePath and LineCurve3 - Add missing event handlers for simulation UI Co-authored-by: leoncoolmoon <2181574+leoncoolmoon@users.noreply.github.com> --- index.html | 4 +- script.js | 113 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/index.html b/index.html index 3ac6d5e..618ad9e 100644 --- a/index.html +++ b/index.html @@ -209,16 +209,14 @@ - diff --git a/script.js b/script.js index 800cb1a..cee60ad 100644 --- a/script.js +++ b/script.js @@ -1745,62 +1745,64 @@ function bt_simulate() { alert("no gcode loaded"); return; } + + var segments = gCode.g1Segments; + if (!segments || segments.length === 0) { + alert("Not enough G1 path data to simulate"); + return; + } + var toolDiameter = parseFloat(document.getElementById('toolDiameter').value); var toolType = document.getElementById('toolType').value; + + var simulationGroup = new THREE.Group(); + if (toolType === "remove") { - //CNC - var cnc = new THREE.Group(); - //use the boundaray of the gcode to draw a 0.5 transparent white box - // 计算模型的包围盒 + // CNC Simulation var boundingBox = new THREE.Box3().setFromObject(gCode); - // 创建白色mash材质 var material = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 }); - // 创建包围盒模型 - var box = new THREE.Mesh(new THREE.BoxGeometry(boundingBox.max.x - boundingBox.min.x, boundingBox.max.y - boundingBox.min.y, boundingBox.max.z - boundingBox.min.z), material); - // 设置包围盒模型的位置 - box.position.set((boundingBox.max.x + boundingBox.min.x) / 2, (boundingBox.max.y + boundingBox.min.y) / 2, (boundingBox.max.z + boundingBox.min.z) / 2); - // 将包围盒模型添加到场景中 - cnc.add(box); - var h = boundingBox.max.z - boundingBox.min.z; - //创造以toolDamteter为半径的圆柱体 - var cylinderGeometry = new THREE.CylinderGeometry(toolDiameter / 2, toolDiameter / 2, h, 32); - var middleShape = new THREE.Shape(); - middleShape.moveTo(0, 0); - middleShape.lineTo(0, h); - middleShape.lineTo(toolDiameter, h); - middleShape.lineTo(toolDiameter, 0); - middleShape.lineTo(0, 0); - var extrudeSettings = { - steps: 100, - bevelEnabled: false, - extrudePath: gCode.children[1] - }; - var extrudeGeometry = new THREE.ExtrudeGeometry(middleShape, extrudeSettings); - var cut = new THREE.Mesh(extrudeGeometry, new THREE.MeshBasicMaterial({ color: 0x000000 })); - cnc.add(cut); - gCode.children[3].forEach(element => { - cylinderGeometry.position.set(element.x, element.y, element.z); - cnc.add(new THREE.Mesh(cylinderGeometry, new THREE.MeshBasicMaterial({ color: 0x000000 }))); - }); - scene.add(cnc); - } - else if (toolType === "add") { - //3dprinter - var curve = gCode.children[1]; - var circleShape = new THREE.Shape(); - circleShape.absarc(0, 0, toolDiameter, 0, Math.PI * 2, false); + var box = new THREE.Mesh( + new THREE.BoxGeometry( + boundingBox.max.x - boundingBox.min.x, + boundingBox.max.y - boundingBox.min.y, + boundingBox.max.z - boundingBox.min.z + ), + material + ); + box.position.set( + (boundingBox.max.x + boundingBox.min.x) / 2, + (boundingBox.max.y + boundingBox.min.y) / 2, + (boundingBox.max.z + boundingBox.min.z) / 2 + ); + simulationGroup.add(box); + } + + var circleShape = new THREE.Shape(); + circleShape.absarc(0, 0, toolDiameter / 2, 0, Math.PI * 2, false); + var meshMaterial = (toolType === "remove") ? + new THREE.MeshBasicMaterial({ color: 0x000000 }) : + new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 }); + + segments.forEach(function (segment) { + if (segment.length < 2) return; + + var curve = new THREE.CurvePath(); + for (var i = 0; i < segment.length - 1; i++) { + curve.add(new THREE.LineCurve3(segment[i], segment[i + 1])); + } + var extrudeSettings = { - steps: 100, + steps: segment.length, bevelEnabled: false, extrudePath: curve }; - // 创建挤出几何体 var extrudeGeometry = new THREE.ExtrudeGeometry(circleShape, extrudeSettings); - // 创建网格并添加到场景中 - var prints = new THREE.Mesh(extrudeGeometry, new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true, opacity: 0.5 })); - scene.add(prints); - } + var mesh = new THREE.Mesh(extrudeGeometry, meshMaterial); + simulationGroup.add(mesh); + }); + + scene.add(simulationGroup); } function adjustAxisFor3DPrint() { @@ -2400,6 +2402,8 @@ function parseGcode(contents, x, y, z, a, lineNumber, pre) { var geometries = new THREE.Group(); geometries.name = "GCODE"; + geometries.g1Segments = []; + var currentSegment = []; //var x = 0, y = 0, z = 0, a = 0; // 增加a变量来保存A轴的值 //var oldx = 0, oldy = 0, oldz = 0, olda = 0; // 增加a变量来保存A轴的值 var oldx = x, oldy = y, oldz = z, olda = a, oldLineNum = lineNumber; // 增加a变量来保存A轴的值 @@ -2438,6 +2442,11 @@ function parseGcode(contents, x, y, z, a, lineNumber, pre) { var tpt = new THREE.Vector3(oldx, oldy, oldz).applyAxisAngle(new THREE.Vector3(0, 1, 0), olda); tpt.name = "1G" + oldLineNum; g0Geometry.vertices.push(tpt); // 在顶点上应用旋转 + + if (currentSegment.length > 1) { + geometries.g1Segments.push(currentSegment); + } + currentSegment = []; } pt.name = "0G" + (i + lineNumber); g0Geometry.vertices.push(pt); //前一段线的终点 @@ -2451,10 +2460,13 @@ function parseGcode(contents, x, y, z, a, lineNumber, pre) { var tpt = new THREE.Vector3(oldx, oldy, oldz).applyAxisAngle(new THREE.Vector3(0, 1, 0), olda); tpt.name = "0G" + oldLineNum; g1Geometry.vertices.push(tpt); // 在顶点上应用旋转 + + currentSegment = [tpt.clone()]; } pt.name = "1G" + (i + lineNumber); g1Geometry.vertices.push(pt); //前一段线的终点 g1Geometry.vertices.push(pt); //后一段线的起点 + currentSegment.push(pt.clone()); oldCode = "G1"; } oldx = x; @@ -2468,6 +2480,9 @@ function parseGcode(contents, x, y, z, a, lineNumber, pre) { // while (g0Geometry.vertices[1] !== g0Geometry.vertices[2]) { g0Geometry.vertices.shift(); } while (g1Geometry.vertices[1] !== g1Geometry.vertices[2]) { g1Geometry.vertices.shift(); } //尾对齐 + if (currentSegment.length > 1) { + geometries.g1Segments.push(currentSegment); + } if (g0Geometry.vertices[g0Geometry.vertices.length - 1] === g0Geometry.vertices[g0Geometry.vertices.length - 2]) { g0Geometry.vertices.pop(); } @@ -2541,3 +2556,11 @@ function calculatePoint3(movePoint, followPoint) { var direction = new THREE.Vector3().subVectors(movePoint, new THREE.Vector3(0, 0, 0)).normalize(); return newPoint1 = direction.clone().multiplyScalar(distance); } + +function toolDiameterChange() { + console.log("toolDiameter changed to: " + document.getElementById('toolDiameter').value); +} + +function toolTypeChange() { + console.log("toolType changed to: " + document.getElementById('toolType').value); +}