优化ui,正在优化gcode_viewer
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user