优化ui,正在优化gcode_viewer

This commit is contained in:
2026-05-16 23:21:20 +08:00
parent d80e8dd05d
commit 1c0fc59738
11 changed files with 1480 additions and 99 deletions

View File

@@ -17,6 +17,7 @@ class GCodeParseWorker(QThread):
points = []
colors = []
type_segments = {}
segment_zs = {}
type_visibility = {}
x = y = z = e = 0.0
@@ -25,6 +26,7 @@ class GCodeParseWorker(QThread):
current_segment_type = 'OTHER'
segment_start = 0
type_visibility['TRAVEL'] = False
relative_e = False
min_x = min_y = min_z = float('inf')
@@ -32,11 +34,16 @@ class GCodeParseWorker(QThread):
current_offset = 0
max_z_seen = -999.0
z_deltas = []
last_layer_z = None
layer_map = [(0, 0)]
layer_grids = {}
segment_visibility = {}
def add_segment(t_name, start, length):
def add_segment(t_name, start, length, z_val):
if length > 0:
type_segments.setdefault(t_name, []).append((start, length))
segment_zs[(start, length)] = z_val
try:
with open(self.filepath, 'rb') as f:
@@ -113,7 +120,10 @@ class GCodeParseWorker(QThread):
if seg_type != current_segment_type:
if vertex_idx > segment_start:
add_segment(current_segment_type, segment_start, vertex_idx - segment_start)
seg_len = vertex_idx - segment_start
add_segment(current_segment_type, segment_start, seg_len, z)
segment_visibility[(segment_start, seg_len)] = (current_segment_type != 'TRAVEL')
# add_segment(current_segment_type, segment_start, vertex_idx - segment_start, z)
current_segment_type = seg_type
segment_start = vertex_idx
@@ -127,6 +137,18 @@ class GCodeParseWorker(QThread):
if new_z > max_z_seen and is_extrusion:
max_z_seen = new_z
layer_map.append((current_offset, vertex_idx))
if last_layer_z is not None:
dz = round(new_z - last_layer_z, 4)
if 0.01 < dz < 2.0:
z_deltas.append(dz)
last_layer_z = new_z
# 建立二维占据网络
if is_extrusion:
grid_z = round(new_z, 2)
gx = int(new_x / 2.0)
gy = int(new_y / 2.0)
layer_grids.setdefault(grid_z,set()).add((gx, gy))
points.extend([x, y, z, new_x, new_y, new_z])
colors.extend([*c, *c])
@@ -144,12 +166,47 @@ class GCodeParseWorker(QThread):
pass
if vertex_idx > segment_start:
add_segment(current_segment_type, segment_start, vertex_idx - segment_start)
# add_segment(current_segment_type, segment_start, vertex_idx - segment_start, z)
seg_len = vertex_idx - segment_start
add_segment(current_segment_type, segment_start, seg_len, z)
segment_visibility[(segment_start, seg_len)] = True
# 判断哪些segment在内部
for type_name, segments in type_segments.items():
if type_name in ('WALL-INNER', 'SUPPORT', 'FILL'):
for start, length in segments:
try:
px = points[start*3]
py = points[start*3+1]
pz = round(points[start*3+2], 2)
gx = int(px / 2.0)
gy = int(py / 2.0)
gird = layer_grids.get(pz, set())
if not gird:
continue
neighbors = 0
# for ox in range(-2,3):
# for oy in range(-2,3):
# if (gx + ox, gy + oy) in gird:
# neighbors += 1
for ox, oy in [(1,0), (-1,0), (0,1), (0,-1)]:
if (gx+ox, gy+oy) in gird:
neighbors += 1
if neighbors >= 4:
segment_visibility[(start, length)] = False
except Exception as e:
pass
cx = (min_x + max_x) / 2.0 if max_x >= min_x else 110.0
cy = (min_y + max_y) / 2.0 if max_y >= min_y else 110.0
cz = (min_z + max_z) / 2.0 if max_z >= min_z else 0.0
from collections import Counter
layer_height = 0.2
if z_deltas:
counter = Counter(z_deltas)
layer_height = counter.most_common(1)[0][0]
result = {
'vertices': np.array(points, dtype=np.float32) if vertex_idx > 0 else np.zeros((0,), dtype=np.float32),
'colors': np.array(colors, dtype=np.float32) if vertex_idx > 0 else np.zeros((0,), dtype=np.float32),
@@ -159,7 +216,10 @@ class GCodeParseWorker(QThread):
'center_z': cz,
'type_segments': type_segments,
'type_visibility': type_visibility,
'layer_map': layer_map
'layer_map': layer_map,
'segment_visibility': segment_visibility,
'segment_zs': segment_zs,
'layer_height': layer_height
}
self.finished.emit(result)
except Exception as e:
@@ -281,6 +341,12 @@ class GCodeViewerWidget(QOpenGLWidget):
self.aColor_location = None
self.uMVP_location = None
# 简化参数
self.enable_lod = True
self.lod_factor = 0.0
self.visible_top_layers = 0
self.visible_bottom_layers = 0
# ── 公开接口 ──
def load_gcode(self, filepath: str):
if hasattr(self, '_worker') and self._worker.isRunning():
@@ -302,8 +368,13 @@ class GCodeViewerWidget(QOpenGLWidget):
self.center_y = result['center_y']
self.center_z = result['center_z']
self.type_segments = result['type_segments']
self.segment_zs = result['segment_zs']
self.type_visibility = result['type_visibility']
self.layer_map = result['layer_map']
self.segment_visibility = result['segment_visibility']
self.min_z = np.min(self.vertices[2::3]) if self.vertex_count > 0 else 0.0
self.max_z = np.max(self.vertices[2::3]) if self.vertex_count > 0 else 0.0
self.vbo_ready = False
# 初始时先不显示,让 update_by_filepos 决定或者如果是0则自动更新
@@ -311,6 +382,7 @@ class GCodeViewerWidget(QOpenGLWidget):
target = 0
if self.layer_map:
target = self.layer_map[-1][1] # 全显
self.layer_height = result.get('layer_height', 0.2)
self.progress_vertices = target
self.last_reported_filepos = -1
@@ -433,24 +505,88 @@ class GCodeViewerWidget(QOpenGLWidget):
# 因此通过动态加粗像素级线宽来性能无损地模拟出“体积感”)
for pass_idx in range(2):
if pass_idx == 0:
gl.glLineWidth(6.0) # 底线宽度(加大以模拟体积轮廓)
if self.enable_lod:
gl.glLineWidth(3.0) # 底线宽度(加大以模拟体积轮廓)
else:
gl.glLineWidth(6.0) # 底线宽度(加大以模拟体积轮廓)
self.shader_program.setUniformValue(self.uDarken_location, 0.8) # 加深颜色至 40% 亮度
else:
gl.glLineWidth(3.0) # 主体宽度(加大以模拟线条厚度)
if self.enable_lod:
gl.glLineWidth(1.5) # 主体宽度(加大以模拟线条厚度)
else:
gl.glLineWidth(3.0) # 主体宽度(加大以模拟线条厚度)
self.shader_program.setUniformValue(self.uDarken_location, 1.0) # 保持原色
# 按类型分段绘制
# for type_name, segments in self.type_segments.items():
# if not self.type_visibility.get(type_name, True):
# continue
# for start, length in segments:
# if start >= self.progress_vertices:
# continue
# end = start + length
# visible_start = start
# visible_count = length
# if end > self.progress_vertices:
# visible_count = self.progress_vertices - start
# if visible_count > 0:
# gl.glDrawArrays(gl.GL_LINES, visible_start, visible_count)
# 按类型分段绘制带LOD
for type_name, segments in self.type_segments.items():
if not self.type_visibility.get(type_name, True):
continue
# 不同类型的简化倍率
simplify_mul = 1
if type_name == 'FILL':
simplify_mul = 3
elif type_name == 'SUPPORT':
simplify_mul = 4
elif type_name == 'TRAVEL':
simplify_mul = 8
# 根据缩放动态增强简化
zoom_mul = max(1.0, abs(self.view_zoom) / 250.0)
# 最终步进
lod_step = 1
if self.enable_lod:
lod_step = int(max(1, self.lod_factor * simplify_mul * zoom_mul))
seg_index = 0
for start, length in segments:
if not self.segment_visibility.get((start, length), True):
continue
if type_name in ('WALL-INNER', 'SUPPORT', 'FILL'):
seg_z = self.segment_zs.get((start, length), self.center_z)
top_limit = self.max_z - self.visible_top_layers * self.layer_height if self.visible_top_layers > 0 else self.min_z - 1.0
bottom_limit = self.min_z + self.visible_bottom_layers * self.layer_height if self.visible_bottom_layers > 0 else self.max_z + 1.0
if bottom_limit <= seg_z <= top_limit:
continue
seg_index += 1
# LOD抽样
if lod_step > 1:
if (seg_index % lod_step) != 0:
continue
if start >= self.progress_vertices:
continue
end = start + length
visible_start = start
visible_count = length
if end > self.progress_vertices:
visible_count = self.progress_vertices - start
if visible_count <= 0:
continue
# 超远距离时进一步减少绘制长度
if self.enable_lod:
if type_name in ('FILL','SUPPORT','WALL-INNER'):
if abs(self.view_zoom) > 400:
if(start // 2) % 3 != 0:
continue
if abs(self.view_zoom) > 700:
if(start // 2) % 6 != 0:
continue
# visible_count = visible_count // 2
if visible_count > 0:
gl.glDrawArrays(gl.GL_LINES, visible_start, visible_count)