如何在Matplotlib中为六芒星的顶点和交点添加数字标注?
六芒星顶点与交点的数字标注实现
问题解决思路
要完成标注,核心是计算六芒星线条的交点坐标。六芒星由6条连接间隔2个顶点的线段组成,任意两条不平行的线段会相交,通过线段交点公式计算这些交点,再结合顶点坐标一起完成数字标注。
完整代码实现
import matplotlib.pyplot as plt import math def get_line_intersection(p1, p2, p3, p4): """计算两条线段p1-p2和p3-p4的交点坐标""" x1, y1 = p1 x2, y2 = p2 x3, y3 = p3 x4, y4 = p4 # 计算分母,判断是否平行 denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) if abs(denom) < 1e-6: return None # 平行或重合,无有效交点 # 计算参数t和u,判断交点是否在线段上 t_num = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4) t = t_num / denom u_num = (x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2) u = -u_num / denom if 0 <= t <= 1 and 0 <= u <= 1: x = x1 + t * (x2 - x1) y = y1 + t * (y2 - y1) return (round(x, 6), round(y, 6)) # 保留6位小数避免浮点误差 else: return None def plot_hexagram_with_numbers(side_length): # 计算六芒星的6个顶点坐标 vertices = [] mu_hexagon = 360 / 6 for i in range(6): angle_rad = math.radians(i * mu_hexagon) x = side_length * math.cos(angle_rad) y = side_length * math.sin(angle_rad) vertices.append((round(x, 6), round(y, 6))) # 生成六芒星的所有边(顶点i到i+2) edges = [(vertices[i], vertices[(i+2) % 6]) for i in range(6)] # 绘制六芒星线条 for edge in edges: x_coords, y_coords = zip(*edge) plt.plot(x_coords, y_coords, 'b-', linewidth=2) # 计算所有交点坐标并去重 intersections = [] for i in range(6): for j in range(i + 1, 6): intersect = get_line_intersection(*edges[i], *edges[j]) if intersect is not None: # 检查是否已存在该交点(避免重复) duplicate = False for pt in intersections: if abs(intersect[0] - pt[0]) < 1e-6 and abs(intersect[1] - pt[1]) < 1e-6: duplicate = True break if not duplicate: intersections.append(intersect) # 合并顶点和交点,准备标注(可自定义数字顺序) all_points = vertices + intersections # 标注数字 label_offset = side_length / 15 # 调整标注偏移量 for idx, (x, y) in enumerate(all_points, 1): # 顶点向外偏移,交点向内偏移 if idx <= 6: # 顶点偏移:沿顶点到原点的反方向移动 offset_x = x * label_offset / side_length offset_y = y * label_offset / side_length plt.text(x + offset_x, y + offset_y, str(idx), fontsize=12, ha='center', va='center') else: # 交点偏移:沿交点到原点的方向移动 offset_x = -x * label_offset / side_length offset_y = -y * label_offset / side_length plt.text(x + offset_x, y + offset_y, str(idx), fontsize=12, ha='center', va='center') # 设置坐标轴等比例,隐藏边框 plt.axis('equal') plt.axis('off') plt.show() # 调用函数生成图示,边长设为2 plot_hexagram_with_numbers(2)
关键部分说明
- 线段交点计算:
get_line_intersection函数通过参数方程求解两条线段的交点,同时判断交点是否在线段范围内,避免无效交点。 - 交点去重:由于每个交点会被两条线段计算两次,通过浮点近似比对来去除重复的交点坐标。
- 标注偏移:顶点标注向外偏移,交点标注向内偏移,避免数字与线条重叠,提升可读性。
内容的提问来源于stack exchange,提问作者Reed Jones
相关产品推荐
相关产品推荐

