You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于GPS坐标数据,如何用Python+Matplotlib绘制斜向椭圆形赛道?

斜向椭圆赛道绘制及轨迹约束实现方案

问题背景

我手头有数百条包含X、Y值的GPS坐标字典数据,转换后得到了MaxX、MaxY、MinX、MinY四个极值。已经用Matplotlib画出了极值红点和特定选手的运动轨迹绿点,需要绘制内外斜向椭圆赛道,要求轨迹绿点既不超出外椭圆边界,也不进入内椭圆区域,但一开始搞不懂斜向椭圆的计算和绘制方法,后来在Brock Brown的帮助下搞定了需求。


1. 斜向椭圆的核心逻辑

斜向椭圆就是标准椭圆经过平移+旋转变换后的结果,关键参数计算如下:

  • 中心坐标:取极值的中点,center_x = (MaxX + MinX)/2,center_y = (MaxY + MinY)/2
  • 半轴长度:外椭圆基于极值差放大5%(避免轨迹贴边),内椭圆取外椭圆半轴的90%;比如外椭圆长半轴a_outer = (MaxX - MinX)/2 * 1.05,短半轴b_outer = (MaxY - MinY)/2 * 1.05
  • 旋转角度:根据极值点的分布方向计算,用np.arctan2(MaxY - MinY, MaxX - MinX)得到弧度后转成角度即可

2. Matplotlib绘制斜向椭圆代码

直接用Matplotlib的Ellipse类就能实现,它原生支持旋转参数:

import matplotlib.pyplot as plt
import numpy as np

# 替换成你的实际极值数据
MaxX, MinX = 100, 0
MaxY, MinY = 80, 20

# 计算椭圆核心参数
center = ((MaxX + MinX)/2, (MaxY + MinY)/2)
# 外椭圆半轴(放大5%预留边界)
a_outer = (MaxX - MinX)/2 * 1.05
b_outer = (MaxY - MinY)/2 * 1.05
# 内椭圆半轴(缩小10%形成赛道区域)
a_inner = a_outer * 0.9
b_inner = b_outer * 0.9
# 旋转角度(弧度转成Matplotlib需要的角度值)
rotate_angle = np.degrees(np.arctan2(MaxY - MinY, MaxX - MinX))

# 创建画布
fig, ax = plt.subplots(figsize=(8,8))

# 绘制外椭圆(灰色半透明填充,黑色边框)
outer_ellipse = plt.matplotlib.patches.Ellipse(
    center, 2*a_outer, 2*b_outer, angle=rotate_angle,
    facecolor='#cccccc', alpha=0.3, edgecolor='black', linewidth=1.5
)
ax.add_patch(outer_ellipse)

# 绘制内椭圆(白色填充覆盖背景,形成赛道区域)
inner_ellipse = plt.matplotlib.patches.Ellipse(
    center, 2*a_inner, 2*b_inner, angle=rotate_angle,
    facecolor='white', edgecolor='black', linewidth=1.5
)
ax.add_patch(inner_ellipse)

# 绘制极值红点
ax.scatter([MaxX, MinX, MaxX, MinX], [MaxY, MinY, MinY, MaxY], color='red', s=60, zorder=3)

# 绘制选手轨迹绿点(替换成你的实际轨迹数据)
np.random.seed(42)
track_x = np.random.uniform(MinX+5, MaxX-5, 120)
track_y = np.random.uniform(MinY+5, MaxY-5, 120)
ax.scatter(track_x, track_y, color='green', s=30, zorder=2)

# 配置坐标轴,保证椭圆比例正确
ax.set_xlim(MinX - 10, MaxX + 10)
ax.set_ylim(MinY - 10, MaxY + 10)
ax.set_aspect('equal')
plt.title('斜向椭圆赛道与选手轨迹')
plt.show()

3. 轨迹点的约束验证

要确保轨迹点落在内外椭圆之间的赛道区域,可以通过坐标变换代入标准椭圆方程判断:

def check_point_valid(x, y, center, outer_a, outer_b, rotate_angle):
    # 平移到椭圆中心
    dx = x - center[0]
    dy = y - center[1]
    # 逆旋转,将点转换到椭圆的局部坐标系
    rad = np.radians(rotate_angle)
    dx_rot = dx * np.cos(rad) + dy * np.sin(rad)
    dy_rot = -dx * np.sin(rad) + dy * np.cos(rad)
    # 验证是否在外椭圆内、内椭圆外(允许微小误差)
    in_outer = (dx_rot/outer_a)**2 + (dy_rot/outer_b)**2 <= 1.01
    out_inner = (dx_rot/(outer_a*0.9))**2 + (dy_rot/(outer_b*0.9))**2 >= 0.99
    return in_outer and out_inner

# 批量验证轨迹点
valid_count = 0
for x, y in zip(track_x, track_y):
    if check_point_valid(x, y, center, a_outer, b_outer, rotate_angle):
        valid_count +=1
print(f"符合赛道约束的轨迹点数量:{valid_count}/{len(track_x)}")

内容的提问来源于stack exchange,提问作者SocketLearner1302

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 06:43:15