在使用Python的Turtle模块做数学图形演示时,很多人会发现它原生只支持画圆,并没有直接提供椭圆绘制接口。如果要画一个长轴沿Y轴方向、且只跨越Y轴一侧的半椭圆,也就是从椭圆顶端到底端、全部位于Y轴右侧或左侧的弧线,就需要借助参数方程来手动算点。这种做法比用形状拉伸更精确,也不会因为变换矩阵产生细微偏差。
一、理解半跨Y轴垂直椭圆的几何定义
所谓垂直椭圆,是指椭圆的长轴与Y轴平行,短轴与X轴平行。假设椭圆中心在坐标原点,长半轴为 b(沿Y方向),短半轴为 a(沿X方向),那么完整椭圆的参数方程可以写作 x = a * sin(t),y = b * cos(t),其中 t 的取值范围是 0 到 2π。当 t 从 0 变到 π 时,y 从 b 降到 -b,而 x 始终大于等于 0,这正好描述了一个位于Y轴右侧、从顶到底的半椭圆,即半跨Y轴的垂直椭圆。
如果希望椭圆跨在Y轴左侧,只需将 x 取负,或者把参数方程改为 x = -a * sin(t)。理解这一点非常重要,因为Turtle的默认坐标系和数学坐标系一致,只要按公式算出坐标并用 goto 移动,就能严格控制图形不越过轴线。很多初学者试图用 turtle.circle 配合 tilt 或 stretch 来凑出椭圆,结果很难保证只画一半且严格贴轴,参数法从原理上规避了这类问题。
二、基础绘制代码实现
下面给出一段最基础的代码,使用 turtle 逐点连线的方式画出右侧半跨Y轴垂直椭圆。我们将角度细分为两百步,保证曲线平滑。注意在 pre 代码块中,所有的小于号和大于号都做了转义处理。
import turtle
import math
# 长半轴(Y方向)和短半轴(X方向)
b = 150
a = 80
t = turtle.Turtle()
t.speed(0)
t.penup()
steps = 200
for i in range(steps + 1):
theta = math.pi * i / steps # 0 到 pi
x = a * math.sin(theta)
y = b * math.cos(theta)
if i == 0:
t.goto(x, y)
t.pendown()
else:
t.goto(x, y)
turtle.done()
这段代码的核心在于 theta 只取 0 到 π,因此 x 始终非负,曲线自然只落在Y轴右侧。如果将 x 改为 -a * math.sin(theta),则图形会出现在左侧。相比起用 circle 加变形,这种写法边界清晰,方便后续在椭圆内部填色或与其他图形拼接。
从性能角度看,二百步的循环对Turtle来说毫无压力,若用于教学演示还可将 steps 调小,让学生直观看到折线如何逼近曲线。同时,由于我们使用了 penup 和 goto 控制起点,不会在落笔前画出多余连线,图形更干净。
三、封装为可复用函数并支持左右跨选
实际项目中,我们往往希望把绘制逻辑封装起来,支持指定中心位置、半轴长度以及跨轴方向。下面的函数接受 cx、cy 作为中心偏移,side 参数控制右侧还是左侧,并返回绘制后的 turtle 对象,便于继续操作。
import turtle
import math
def draw_half_ellipse(cx, cy, a, b, side='right', steps=300):
t = turtle.Turtle()
t.speed(0)
t.penup()
sign = 1 if side == 'right' else -1
for i in range(steps + 1):
theta = math.pi * i / steps
x = cx + sign * a * math.sin(theta)
y = cy + b * math.cos(theta)
if i == 0:
t.goto(x, y)
t.pendown()
else:
t.goto(x, y)
return t
if __name__ == '__main__':
draw_half_ellipse(0, 0, 80, 150, side='right')
turtle.done()
通过 sign 变量,我们只需改变正负就能切换左右跨Y轴,而中心坐标 cx、cy 让椭圆可以画在画布任意位置。这种封装方式在需要组合多个半椭圆构成花瓣、拱门等图案时尤其有用。比如将四个不同方向的半椭圆拼起来,就能得到完整的椭圆或特殊装饰图形。
需要注意,Turtle的画布坐标范围有限,若 b 设置过大可能超出可视区域,调用前应根据窗口大小调整。另外,如果要在函数中隐藏海龟箭头,可加上 t.hideturtle(),让输出更像一个静态图形而不是绘图过程。
四、填充与常见误区
绘制完半椭圆后,经常需要填充颜色。此时应在循环前调用 t.begin_fill(),循环结束后调用 t.end_fill()。但要小心:因为我们的路径只是开放弧线,直接填充会让Turtle自动用直线连回起点形成封闭区域,这恰好是我们要的半椭圆盘。若不想封闭,就不要启用填充。
import turtle
import math
t = turtle.Turtle()
t.speed(0)
b = 120
a = 60
t.penup()
t.begin_fill()
for i in range(301):
theta = math.pi * i / 300
x = a * math.sin(theta)
y = b * math.cos(theta)
if i == 0:
t.goto(x, y)
t.pendown()
else:
t.goto(x, y)
t.end_fill()
turtle.done()
一个常见误区是认为 turtle.circle(radius, extent) 的 extent 设成 180 就是半椭圆,其实它画出的只是半圆,无论怎么拉伸都难以精确匹配参数方程给出的半轴比例。另一个误区是忽略海龟朝向,用 forward 加左右转去逼近,这种方法累积误差大,且代码难读。直接用 goto 与数学公式,才是精确绘制半跨Y轴垂直椭圆的稳妥方案。
总结来看,只要掌握参数方程中 t 的范围与坐标符号,Python Turtle完全可以胜任严谨的数学曲线绘制,而不只是儿童涂鸦工具。将上述函数略作修改,还能画出任意角度的椭圆弧,扩展性强。
Python_Turtle垂直椭圆半跨Y轴修改时间:2026-08-05 18:39:40