You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

267 lines
11 KiB

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}")