from math import cos, pi import matplotlib.pyplot as plt blue_fill_color = (0.4, 0.8, 1.0, 0.6) blue_edge_color = (0.4, 0.8, 1.0, 0.3) red_fill_color = (1.0, 0.8, 0.4, 0.6) red_edge_color = (1.0, 0.8, 0.4, 0.3) draw_state = 0 plt.rcParams['font.family'] = ['Times New Roman', 'SimSun'] plt.rcParams['mathtext.fontset'] = 'stix' plt.rcParams['font.size'] = 16 def read_meta_data(filename): with open(filename, 'r', encoding='utf-8') as file: content = file.read() blocks = [block.strip() for block in content.strip().split('\n\n')] meta_data = {} meta_data['type'] = blocks[0].strip() lines = blocks[1].strip().split('\n') meta_data['chain_range'] = [] meta_data['chain_double_sided'] = [] meta_data['chain_point_to_pos_side'] = [] for i, line in enumerate(lines): line = line.strip() parts = line.split() meta_data['chain_range'].append((int(parts[0]), int(parts[1]))) meta_data['chain_double_sided'].append(True if parts[2] == 'true' else False) meta_data['chain_point_to_pos_side'].append(True if parts[3] == 'true' else False) meta_data['aabb'] = [] lines = blocks[2].strip().split('\n') parts = lines[0].strip().split() for part in parts: meta_data['aabb'].append(float(part)) meta_data['parallel_to_u'] = [] meta_data['parallel_to_v'] = [] meta_data['intersect_u'] = [] meta_data['intersect_v'] = [] lines = blocks[3].strip().split('\n') parts = lines[0].strip().split() for part in parts: meta_data['parallel_to_v'].append(float(part)) parts = lines[1].strip().split() for part in parts: meta_data['intersect_u'].append(float(part)) parts = lines[2].strip().split() for part in parts: meta_data['parallel_to_u'].append(float(part)) parts = lines[3].strip().split() for part in parts: meta_data['intersect_v'].append(float(part)) # print("Meta Data:") # print(f"Type: {meta_data['type']}") # print("Chain Ranges:") # for i, chain_range in enumerate(meta_data['chain_range']): # print(f" Subchain {i+1}: {chain_range[0]} to {chain_range[1]}") # print("Chain Double Sided:") # for i, double_sided in enumerate(meta_data['chain_double_sided']): # print(f" Subchain {i+1}: {'Yes' if double_sided else 'No'}") # print("Chain Point to Pos Side:") # for i, point_to_pos_side in enumerate(meta_data['chain_point_to_pos_side']): # print(f" Subchain {i+1}: {'Yes' if point_to_pos_side else 'No'}") # print("Parallel to U:", meta_data['parallel_to_u']) # print("Intersect U:", meta_data['intersect_u']) # print("Parallel to V:", meta_data['parallel_to_v']) # print("Intersect V:", meta_data['intersect_v']) return meta_data def read_integral_points(filename): integral_points = [] with open(filename, 'r', encoding='utf-8') as file: content = file.read() lines = content.strip().split('\n') for line in lines: line = line.strip() if not line: continue parts = line.split() try: u = float(parts[0]) v = float(parts[1]) weight = float(parts[2]) integral_points.append((u, v, weight)) except ValueError: print(f"警告: 积分点行 '{line}' 包含非数字内容,跳过") continue # 对权值进行一致化并存储到最后一维 min_weight = min(weight for _, _, weight in integral_points) max_weight = max(weight for _, _, weight in integral_points) for i in range(len(integral_points)): u, v, weight = integral_points[i] normalized_weight = (weight - min_weight) / (max_weight - min_weight) if max_weight > min_weight else 0 integral_points[i] = (u, v, weight, normalized_weight) return integral_points def read_and_plot_polylines(filename, meta_data, integral_points): # 读取文件内容 with open(filename, 'r', encoding='utf-8') as file: content = file.read() # 按空行分割不同的折线段区块 # strip() 用于移除开头和结尾的空行,split('\n\n') 按连续换行分割 blocks = [block.strip() for block in content.strip().split('\n\n')] # 创建图形 plt.figure(figsize=(10, 8)) # 处理每个区块 for i, block in enumerate(blocks): if not block: # 跳过空区块 continue # 匹配chain的meta信息 double_sided = False point_to_pos_side = False for (chain_range, double_sided_, point_to_pos_side_) in zip(meta_data['chain_range'], meta_data['chain_double_sided'], meta_data['chain_point_to_pos_side']): if chain_range[0] <= i < chain_range[1]: double_sided = double_sided_ point_to_pos_side = point_to_pos_side_ break # 将区块分割成行 lines = block.strip().split('\n') # 存储当前折线段的点 x_points = [] y_points = [] # 处理每一行 for line in lines: line = line.strip() if not line: # 跳过空行 continue # 分割两个double数值 parts = line.split() try: x = float(parts[0]) y = float(parts[1]) x_points.append(x) y_points.append(y) except ValueError: print(f"警告: 区块 {i+1} 的行 '{line}' 包含非数字内容,跳过") continue if draw_state > 0: for ((x1, x2), (y1, y2)) in zip(zip(x_points, x_points[1:]), zip(y_points, y_points[1:])): delta_x = x2 - x1 delta_y = y2 - y1 # (delta_y, -delta_x) 为正方向向量 point_to_neg_x = (not point_to_pos_side and delta_y > 0) or (point_to_pos_side and delta_y < 0) point_to_pos_x = (point_to_pos_side and delta_y > 0) or (not point_to_pos_side and delta_y < 0) point_to_neg_y = (not point_to_pos_side and delta_x < 0) or (point_to_pos_side and delta_x > 0) point_to_pos_y = (point_to_pos_side and delta_x < 0) or (not point_to_pos_side and delta_x > 0) if double_sided: if draw_state == 1: plt.fill([-100, -100, 100, 100], [y1, y2, y2, y1], facecolor=blue_fill_color, edgecolor=blue_edge_color) elif draw_state == 2: plt.fill([x1, x2, x2, x1], [-100, -100, 100, 100], facecolor=red_fill_color, edgecolor=red_edge_color) else: if draw_state == 1: if point_to_neg_x: plt.fill([x1, x2, -100, -100], [y1, y2, y2, y1], facecolor=blue_fill_color, edgecolor=blue_edge_color) elif point_to_pos_x: plt.fill([x1, x2, 100, 100], [y1, y2, y2, y1], facecolor=blue_fill_color, edgecolor=blue_edge_color) elif draw_state == 2: if point_to_neg_y: plt.fill([x1, x1, x2, x2], [y1, -100, -100, y2], facecolor=red_fill_color, edgecolor=red_edge_color) elif point_to_pos_y: plt.fill([x1, x1, x2, x2], [y1, 100, 100, y2], facecolor=red_fill_color, edgecolor=red_edge_color) # 绘制当前折线段 plt.plot(x_points, y_points, marker='o', linestyle='-', color='black', label=f'Subchain {i+1}', linewidth=2, markersize=4) # 绘制平行线和交点 if draw_state == 3: for u in meta_data['parallel_to_u']: plt.axhline(y=u, color='red', linestyle='--', linewidth=3, alpha=0.7) for v in meta_data['parallel_to_v']: plt.axvline(x=v, color='red', linestyle='--', linewidth=3, alpha=0.7) for i in range(len(meta_data['intersect_u'])): u = meta_data['intersect_u'][i] v = meta_data['intersect_v'][i] # 加粗交点标记 plt.plot(u, v, marker='x', color='red', markersize=12, markeredgewidth=2, label=f'Intersect {i+1}') # 绘制带权值的积分点 if draw_state == 4: u_vals, v_vals, weights, normalized_weights = zip(*integral_points) plt.scatter(u_vals, v_vals, c=normalized_weights, cmap='viridis', s=50, alpha=0.7, label='Integral Points') print(f"积分点权值总和: {sum(weights)}") x_min = meta_data['aabb'][0] x_max = meta_data['aabb'][2] y_min = meta_data['aabb'][1] y_max = meta_data['aabb'][3] x_range = x_max - x_min y_range = y_max - y_min if x_range == 0: x_padding = abs(x_max) * 0.1 if x_max != 0 else 0.5 else: x_padding = max(x_range * 0.05, x_range * 0.005) if y_range == 0: y_padding = abs(y_max) * 0.1 if y_max != 0 else 0.5 else: y_padding = max(y_range * 0.05, y_range * 0.005) # 设置坐标轴范围 plt.xlim(x_min - x_padding, x_max + x_padding) plt.ylim(y_min - y_padding, y_max + y_padding) # 提示AABB plt.plot([x_min, x_max, x_max, x_min, x_min], [y_min, y_min, y_max, y_max, y_min], linestyle='-', color='green', label='AABB', linewidth=1) # 设置图形属性 # plt.title('') plt.xlabel('u坐标') plt.ylabel('v坐标') plt.grid(True, alpha=0.3) # plt.legend() # 保持x和y轴比例相同(但会因y轴padding而稍有不同) plt.gca().set_aspect('auto') # 显示图形 plt.tight_layout() plt.show() # 使用示例 if __name__ == "__main__": # 或者使用您自己的文件 filename = input("请输入文件路径: ").strip() print("绘制模式选项:") print("0: 仅绘制折线段") print("1: 绘制折线段并标注U方向可行域") print("2: 绘制折线段并标注V方向可行域") print("3: 绘制折线段并标注U和V方向的区间分段") print("4: 绘制折线段并绘制带权值的积分点") draw_state = int(input("请输入绘制模式:").strip()) try: meta_data = read_meta_data(filename + ".meta") integral_points = read_integral_points(filename + ".int2d") read_and_plot_polylines(filename + ".txt", meta_data, integral_points) except FileNotFoundError: print(f"错误: 文件 '{filename}' 未找到") except Exception as e: print(f"发生错误: {e}")