Skip to content

Commit aa6ac8a

Browse files
committed
add cut function
1 parent 7176763 commit aa6ac8a

3 files changed

Lines changed: 252 additions & 60 deletions

File tree

index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@
173173
target="_blank" style = "color:beige; justify-content: center; display: grid; text-shadow: gray 0.1em 0.1em 0.2em;
174174
">Buy me a coffee!</a>
175175
<div id="imageContainer">
176-
<img src="alipay.jpg" alt="Image 1">
177-
<img src="paypal.jpg" alt="Image 2">
178-
<img src="wechat.png" alt="Image 3">
176+
<img src="./alipay.jpg" alt="Image 1">
177+
<img src="./paypal.jpg" alt="Image 2">
178+
<img src="./wechat.png" alt="Image 3">
179179
</div>
180180

181181
</div>

script.js

Lines changed: 88 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var supressCube = false;
1818
var isASCII = false;
1919
var landscape = true;
2020
var cordinatesDiv = document.getElementById('cordinates');
21+
var nromalTitle = "STL Gcode Viewer";
2122
// 创建球体对象
2223
// var cursor3D = new THREE.Group();
2324
// cursor3D.name = "cursor";
@@ -43,59 +44,59 @@ var cordinatesDiv = document.getElementById('cordinates');
4344
// sizeAttenuation: false, // 关闭点的大小衰减
4445
// transparent: true // 开启透明度
4546
// })));
46-
var canvas = document.createElement('canvas');
47-
canvas.width = 64;
48-
canvas.height = 64;
49-
var context = canvas.getContext('2d');
50-
51-
// 绘制十字光标 - 改成亮黄色
52-
context.strokeStyle = '#ffff00';
53-
context.lineWidth = 3;
54-
55-
// 左横线
56-
context.beginPath();
57-
context.moveTo(10, 32);
58-
context.lineTo(28, 32);
59-
context.stroke();
60-
61-
// 右横线
62-
context.beginPath();
63-
context.moveTo(36, 32);
64-
context.lineTo(54, 32);
65-
context.stroke();
66-
67-
// 上竖线
68-
context.beginPath();
69-
context.moveTo(32, 10);
70-
context.lineTo(32, 28);
71-
context.stroke();
72-
73-
// 下竖线
74-
context.beginPath();
75-
context.moveTo(32, 36);
76-
context.lineTo(32, 54);
77-
context.stroke();
78-
79-
// 中心圆形 - 镂空边框
80-
context.strokeStyle = 'rgba(247, 113, 113, 1)';
81-
context.lineWidth = 1;
82-
context.beginPath();
83-
context.arc(32, 32, 2, 0, 2 * Math.PI);
84-
context.stroke();
85-
86-
var cursorMap = new THREE.CanvasTexture(canvas);
87-
var spriteMaterial = new THREE.SpriteMaterial({
88-
map: cursorMap,
89-
transparent: true,
90-
opacity: 0.8,
91-
depthTest: false, // 关键:不受深度测试影响
92-
depthWrite: false // 关键:不写入深度缓冲区
93-
});
94-
95-
cursor3D = new THREE.Sprite(spriteMaterial);
96-
cursor3D.name = "cursor";
97-
cursor3D.scale.set(20, 20, 1); // 屏幕空间尺寸(像素)
98-
cursor3D.visible = false;
47+
var canvas = document.createElement('canvas');
48+
canvas.width = 64;
49+
canvas.height = 64;
50+
var context = canvas.getContext('2d');
51+
52+
// 绘制十字光标 - 改成亮黄色
53+
context.strokeStyle = '#ffff00';
54+
context.lineWidth = 3;
55+
56+
// 左横线
57+
context.beginPath();
58+
context.moveTo(10, 32);
59+
context.lineTo(28, 32);
60+
context.stroke();
61+
62+
// 右横线
63+
context.beginPath();
64+
context.moveTo(36, 32);
65+
context.lineTo(54, 32);
66+
context.stroke();
67+
68+
// 上竖线
69+
context.beginPath();
70+
context.moveTo(32, 10);
71+
context.lineTo(32, 28);
72+
context.stroke();
73+
74+
// 下竖线
75+
context.beginPath();
76+
context.moveTo(32, 36);
77+
context.lineTo(32, 54);
78+
context.stroke();
79+
80+
// 中心圆形 - 镂空边框
81+
context.strokeStyle = 'rgba(247, 113, 113, 1)';
82+
context.lineWidth = 1;
83+
context.beginPath();
84+
context.arc(32, 32, 4, 0, 2 * Math.PI);
85+
context.stroke();
86+
87+
var cursorMap = new THREE.CanvasTexture(canvas);
88+
var spriteMaterial = new THREE.SpriteMaterial({
89+
map: cursorMap,
90+
transparent: true,
91+
opacity: 0.8,
92+
depthTest: false, // 关键:不受深度测试影响
93+
depthWrite: false // 关键:不写入深度缓冲区
94+
});
95+
96+
cursor3D = new THREE.Sprite(spriteMaterial);
97+
cursor3D.name = "cursor";
98+
cursor3D.scale.set(20, 20, 1); // 屏幕空间尺寸(像素)
99+
cursor3D.visible = false;
99100
// 定义一个射线投射器
100101
var raycaster = new THREE.Raycaster();
101102
var mouse = new THREE.Vector2();
@@ -1171,7 +1172,6 @@ function jumpToLayer(layerNumber) {
11711172
txar.setCursor(startLine, 0);
11721173
markLine(startLine, true);
11731174
layerData.currentLayer = layerNumber;
1174-
11751175
// 更新进度条显示
11761176
updateProgressBarDisplay();
11771177

@@ -1207,10 +1207,40 @@ function extractLayerNumber(line) {
12071207
var match = line.match(/;LAYER:(\d+)/);
12081208
return match ? parseInt(match[1]) : -1;
12091209
}
1210-
1211-
function bt_cut(){
1212-
1210+
const worker = new Worker('./worker.js');
1211+
function bt_cut() {
1212+
if (machineType !== "3DPRINT") return;
1213+
if (document.title === nromalTitle) return;
1214+
var cutBt = document.getElementById("cuthere");
1215+
//disable cutBt after been used
1216+
cutBt.disabled = true;
1217+
cutBt.innerText = "processing...";
1218+
const cursorPos = txar.getCursor();
1219+
const text = txar.getValue(); // CodeMirror 文本
1220+
const cursorLine = txar.getCursor().line; // 当前光标行
1221+
const title = document.title; // 页面标题
1222+
1223+
// 发送给 worker
1224+
worker.postMessage({
1225+
text,
1226+
cursorLine,
1227+
title
1228+
});
12131229
}
1230+
// 接收处理结果并下载
1231+
worker.onmessage = e => {
1232+
const { fileName, content } = e.data;
1233+
const blob = new Blob([content], { type: 'text/plain' });
1234+
const a = document.createElement('a');
1235+
a.href = URL.createObjectURL(blob);
1236+
a.download = fileName;
1237+
a.click();
1238+
URL.revokeObjectURL(a.href);
1239+
var cutBt = document.getElementById("cuthere");
1240+
cutBt.innerText = "cut here";
1241+
cutBt.disabled = false;
1242+
};
1243+
12141244

12151245
function bt_open() {
12161246
//pop open file diaglog to open local file accept extension in plainTextFile and STL
@@ -1248,6 +1278,7 @@ function read_file(file) {
12481278
alert("file size is too big");
12491279
return;
12501280
}
1281+
document.title = file.name;
12511282
scene.remove(sampleCube);
12521283
if (gCode !== undefined) {
12531284
gCodeClear();

worker.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
function findLastPositions(lines, startLine) {
2+
let lastE = null, lastZ = null, lastX = null, lastY = null;
3+
4+
// 从起始行向前倒着查找(保持您原来的逻辑)
5+
for (let i = startLine - 2; i >= 0; i--) {
6+
const line = lines[i].trim();
7+
8+
if (!line || line.startsWith(';')) continue;
9+
10+
// 只处理运动指令
11+
if (line.startsWith('G0') || line.startsWith('G1')) {
12+
if (line.includes('E') && lastE === null) {
13+
const match = line.match(/E([-]?\d+\.\d+)/);
14+
if (match) lastE = match[1];
15+
}
16+
17+
if (line.includes('Z') && lastZ === null) {
18+
const match = line.match(/Z([-]?\d+\.\d+)/);
19+
if (match) lastZ = match[1];
20+
}
21+
22+
if (line.includes('X') && lastX === null) {
23+
const match = line.match(/X([-]?\d+\.\d+)/);
24+
if (match) lastX = match[1];
25+
}
26+
27+
if (line.includes('Y') && lastY === null) {
28+
const match = line.match(/Y([-]?\d+\.\d+)/);
29+
if (match) lastY = match[1];
30+
}
31+
}
32+
33+
// 如果所有值都找到就退出
34+
if (lastE !== null && lastZ !== null && lastX !== null && lastY !== null) {
35+
break;
36+
}
37+
}
38+
39+
return {
40+
e: lastE || "0.0",
41+
z: lastZ || "0.0",
42+
x: lastX || "0.0",
43+
y: lastY || "0.0"
44+
};
45+
}
46+
function processGcodeInBackground(content, startLine, originalFilename) {
47+
try {
48+
// 分割文件内容
49+
const lines = content.split('\n');
50+
51+
// 验证行号
52+
if (startLine < 1 || startLine > lines.length) {
53+
throw new Error(`行号应在 1-${lines.length} 范围内`);
54+
}
55+
56+
// 查找头部结束位置
57+
const headerEndLine = findHeaderEndLine(lines);
58+
if (headerEndLine == 0) {
59+
throw new Error("no header, cut failed")
60+
}
61+
// 查找最后一个有效位置
62+
const lastPositions = findLastPositions(lines, startLine);
63+
64+
// 提取温度设置
65+
const temperatures = extractTemperatures(lines);
66+
67+
// 生成新的G代码
68+
const newGcode = generateNewGcode(
69+
lines,
70+
startLine,
71+
headerEndLine,
72+
lastPositions,
73+
temperatures
74+
);
75+
76+
// 创建下载链接
77+
downloadFile(newGcode, originalFilename, startLine);
78+
79+
showStatus(`文件切割完成!新文件从第 ${startLine} 行开始`, 'success');
80+
progressBar.style.display = 'none';
81+
} catch (e) {
82+
showStatus(e, 'error');
83+
84+
}
85+
}
86+
function findHeaderEndLine(lines) {
87+
for (let i = 0; i < lines.length; i++) {
88+
const line = lines[i].trim();
89+
if (line.startsWith(';LAYER_COUNT')) {
90+
return i;
91+
}
92+
}
93+
return 0;
94+
}
95+
function extractTemperatures(lines) {
96+
let nozzleTemp = "0";
97+
let bedTemp = "0";
98+
99+
for (const line of lines) {
100+
if (line.startsWith('M104')) {
101+
const match = line.match(/S(\d+)/);
102+
if (match) nozzleTemp = match[1];
103+
}
104+
if (line.startsWith('M190')) {
105+
const match = line.match(/S(\d+)/);
106+
if (match) bedTemp = match[1];
107+
}
108+
}
109+
110+
return { nozzleTemp, bedTemp };
111+
}
112+
function generateNewGcode(lines, startLine, headerEndLine, positions, temps) {
113+
let newContent = '';
114+
115+
// 添加新的文件头
116+
newContent += `; Regenerated G code - from line ${startLine} \n`;
117+
newContent += 'M117 start heating...\n';
118+
newContent += `M104 S${temps.nozzleTemp} ; set\n`;
119+
newContent += `M109 S${temps.nozzleTemp} ; wait nozzle temperature\n`;
120+
121+
newContent += 'M117 ready to print...\n';
122+
newContent += 'G28 X Y ; homing XY\n';
123+
newContent += 'G28 Z ; homing Z\n';
124+
125+
// 移动到安全高度
126+
const safeZ = parseFloat(positions.z) + 5.0;
127+
newContent += `G0 Z${safeZ.toFixed(3)} F3000 ; move Z to safe height\n`;
128+
129+
// 移动到最后位置
130+
newContent += `G0 X${positions.x} Y${positions.y} F3000 ; move X Y to breakup point\n`;
131+
132+
// 设置挤出机位置
133+
newContent += `G92 E${positions.e} ; set Excluder\n`;
134+
newContent += `M117 resume from ${startLine} ...\n\n`;
135+
136+
// 添加从指定行开始的内容
137+
for (let i = startLine - 1; i < lines.length; i++) {
138+
newContent += lines[i] + '\n';
139+
}
140+
141+
return newContent;
142+
}
143+
function downloadFile(content, originalFilename, startLine) {
144+
145+
// 将结果回传给主线程
146+
self.postMessage({
147+
fileName: `${`${originalFilename}_resume_from_line_${startLine}.gcode` || 'output'}.gcode`,
148+
content: content
149+
});
150+
}
151+
152+
// worker.js
153+
self.onmessage = e => {
154+
const { text, cursorLine, title } = e.data;
155+
156+
processGcodeInBackground(text, cursorLine, title)
157+
const processed =
158+
`# Title: ${title}\n# Cursor Line: ${cursorLine}\n\n${text}`;
159+
// =================================
160+
161+
};

0 commit comments

Comments
 (0)