🌈据说,看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。
前言:
🧡作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
✨个人主页:点我直达,在这里肯定能找到你想要的~
👍专栏介绍:Python绘图 ,一个专注于分享绘图案例与教学的专栏~
专栏文章直链:
【Python绘图】绘图常见的构成元素1
【Python绘图】学习绘图第一步,先要知道哪些操作是常用的
【Python绘图】朋友过生日不知道送什么?免费的蛋糕送给他
Python基础图形绘图教学2
绘画正多边形内邻点连线图形(含偶数边数)
import turtle
def draw_polygon(location, radius, side):
if radius % 2:
draw_odd_polygon(location, radius, side)
else:
turtle.penup()
turtle.goto(*location)
turtle.pendown()
turtle.circle(radius=-radius, extent=360, steps=side // 2)
turtle.penup()
turtle.setheading(-90)
turtle.forward(radius)
turtle.setheading(90 - 360 / side)
turtle.forward(radius)
turtle.setheading(-360 / side)
turtle.pendown()
turtle.circle(radius=-radius, extent=360, steps=side // 2)
turtle.setup(400, 400)
draw_polygon((0, 100), 100, 10)
turtle.exitonclick()
这里利用昨天制作的 draw_odd_polygon(location, radius, side)
函数处理单边情况,当然写在这个函数里也可以,至于我为什么要把单边绘画单独拎出来呢,我也不知道,也许我感觉单边奇特就单独拿出来了😂也许是因为单身😅也许是因为今天是4月1号是个奇数日😁也许…
绘画椭圆形——引言:圆的三种画法
画圆很简单,一个函数就能搞定,但假如没有函数怎么画?这里有三种方法:
这里是博主之前画正多边形内邻点连线图形从三边形画到了一百边形,是按半径画的,现在是不是发现,这画起来外形就是一个圆?的确,所以圆除了用turtle自带的circle函数画之外,还可以使用 n 边形,多到这里的 n 足够大、边长特别小,小到 1 像素就可以了~
先来试试10边形画出来的圆:
import turtle
turtle.setup(300, 300)
turtle.penup()
turtle.goto(0, 100)
turtle.pendown()
for i in range(10):
turtle.forward(50)
turtle.right(36)
turtle.penup()
turtle.exitonclick()
现在多边形的影子还是很明显的,不过如果边长从50变成10,不放大看,那肯定也看不出来了,接下来使用20边形画出来的圆:
import turtle
turtle.setup(300, 300)
turtle.penup()
turtle.goto(0, 100)
turtle.pendown()
for i in range(20):
turtle.forward(30)
turtle.right(18)
turtle.penup()
turtle.exitonclick()
现在基本上看起来像个圆了,不过还是能看到点钝角,使用60边形画出来的圆:
import turtle
turtle.setup(300, 300)
turtle.penup()
turtle.goto(0, 100)
turtle.pendown()
for i in range(60):
turtle.forward(10)
turtle.right(6)
turtle.penup()
turtle.exitonclick()
现在不放大已经看不出这是一个多边形而不是圆了,接下来我们放大看看:
再放大画圆的图形:
已经看不出区别了,甚至感觉默认的圆就是这么画出来的,所以对于这么大小的圆,在放大如此倍数的情况下,已经不需要再用更多边、更短边长了~当然用更多边、更短边长肯定越像。
接下来使用圆的直角坐标方程绘画:x2 + y2 = 502 => y = (502 - x2) 1/2
所以使用如下代码:
import turtle
turtle.setup(300, 300)
turtle.penup()
turtle.goto(50, 0)
turtle.pendown()
# x^2 + y^2 = 50^2 => y = (50^2 - x^2) ^ 0.5
for x in range(50, -50, -1):
turtle.goto(x, (50 ** 2 - x ** 2) ** 0.5)
for x in range(-50, 50 + 1):
turtle.goto(x, -(50 ** 2 - x ** 2) ** 0.5)
turtle.penup()
turtle.exitonclick()
画的圆真不错~接下来再使用极坐标方程画圆:x = r * cos(α); y = r * sin(α)
所以使用如下代码:
import math
import turtle
turtle.setup(300, 300)
turtle.penup()
turtle.goto(50, 0)
turtle.pendown()
# x = r * cos(α); y = r * sin(α)
for a in range(360):
turtle.goto(50 * math.cos(math.radians(a + 1)), 50 * math.sin(math.radians(a + 1)))
turtle.penup()
turtle.exitonclick()
这种方式画小圆就会显得比较慢,但很细致!
接下来就分别用这三种方法来画椭圆~
绘画椭圆形——数量足够大的多边形
现在来模仿上面画圆的方法,画两段180°的弧线,前一半逐渐增长单位距离,后一半逐渐减小单位距离,然后重复一次画完上下两半:
import turtle
turtle.setup(300, 200)
turtle.penup()
turtle.setheading(90)
turtle.goto(-100, 0)
turtle.pendown()
fd = 1 # 前进的距离
for _ in range(2):
for i in range(60):
if i < 30:
fd += 0.2
else:
fd -= 0.2
turtle.forward(fd)
turtle.right(3)
turtle.penup()
turtle.exitonclick()
绘画椭圆形——椭圆直角坐标方程
接下来使用椭圆的直角坐标方程绘画:x2 / a2 + y2 / b2 = 1 (焦点在X轴上) => y = (((a2 - x2) * b2) / a2) 1/2
所以使用如下代码:
import turtle
turtle.setup(300, 200)
turtle.penup()
turtle.forward(100)
turtle.setheading(90)
turtle.pendown()
# x^2 / a^2 + y^2 / b^2 = 1 (焦点在X轴上) => y = (((a^2 - x^2) * b^2) / a^2) ^ 0.5
for x in range(100, -100, -1):
turtle.goto(x, (((100 ** 2 - x ** 2) * 60 ** 2) / 100 ** 2) ** 0.5)
for x in range(-100, 100 + 1):
turtle.goto(x, -1 * (((100 ** 2 - x ** 2) * 60 ** 2) / 100 ** 2) ** 0.5)
turtle.penup()
turtle.exitonclick()
上一个方法不太容易控制椭圆的长轴和短轴,但从接下来的直接坐标方程和接下来的极坐标方程就能画出可控制长轴短轴的椭圆了。
绘画椭圆形——椭圆参数方程
所以使用如下代码:
import math
import turtle
turtle.setup(300, 200)
turtle.penup()
turtle.goto(100, 0)
turtle.pendown()
# x = a * cos(β); y = b * sin(β)
for a in range(360):
turtle.goto(100 * math.cos(math.radians(a + 1)), 60 * math.sin(math.radians(a + 1)))
turtle.penup()
turtle.exitonclick()
合理计算绘画椭圆形最短时间的方法
方法虽多,但合理选择能够提高程序运行的速度,首先第一种方法肯定排除定量画了
毕竟不好掌控,接下来来对比不同场景下直角坐标绘图和参数方程绘图的速度快慢。
使用如下代码进行测速,其中a是半长轴长度,b是半短轴长度:
import timeit
a, b = 100, 60
zj = f"""import math, turtle
turtle.setup({a * 3}, {b * 4})
turtle.penup()
turtle.forward({a})
turtle.setheading(90)
turtle.pendown()
for x in range({a}, -{a}, -1):
turtle.goto(x, ((({a} ** 2 - x ** 2) * {b} ** 2) / {a} ** 2) ** 0.5)
for x in range(-{a}, {a} + 1):
turtle.goto(x, -1 * ((({a} ** 2 - x ** 2) * {b} ** 2) / {a} ** 2) ** 0.5)
turtle.penup()"""
cs = f"""import math, turtle
turtle.setup({a * 3}, {b * 4})
turtle.penup()
turtle.goto({a}, 0)
turtle.pendown()
for a in range(360):
turtle.goto({a} * math.cos(math.radians(a + 1)), {b} * math.sin(math.radians(a + 1)))
turtle.penup()"""
print(timeit.timeit(stmt=zj, number=1)) # 直角坐标系画椭圆
print(timeit.timeit(stmt=cs, number=1)) # 参数方程画椭圆
实验了三次,可以发现在a和b都比较小的情况下,参数方程绘图速度明显优于直角坐标系绘画,接下来尝试a >> b(a远远大于b) 和 a和b都比较大两种情况,就不截图直接上结果了:
a >> b(a远远大于b)时 (a = 400, b = 60) :
27.0443778
6.384453299999997
这里已经很明显的发现,直角坐标速度特别特别的慢,所以就不做多次测试了,再看看a和b都比较大的时候数据 (a = 400, b = 240) :
27.2738971
6.614392299999999
发现没有什么变化,这应该看出来了,不管a和b怎么变化,参数方程绘画时间都约6秒钟,但直接坐标系绘画取决于a的大小,所以第一次测的时候a还是太大了,现在换等比更小的数据试试 (a = 50, b = 30) :
3.7825953
6.099516699999999
现在发现,直角坐标系绘画速度明显优于参数方程绘图了,所以我们可以根据a的大小计算使用哪种方法,经测试发现,a为90的时候两者速度差不多,所以可以根据这个划分使用场景。
绘画圆柱体
在之前绘画蛋糕的过程中,绘制了顶部和侧边颜色不同的圆柱体,如何在椭圆上绘制这种层次关系呢?这里使用上方的参数方程(因为代码少)来绘画一个:
import math
import turtle
turtle.setup(300, 400)
turtle.penup()
turtle.goto(100, -40)
turtle.color('pink')
turtle.pendown()
turtle.begin_fill()
for a in range(360):
turtle.goto(100 * math.cos(math.radians(a + 1)), -40 + 60 * math.sin(math.radians(a + 1)))
turtle.setheading(90)
turtle.forward(80)
turtle.setheading(180)
turtle.forward(200)
turtle.setheading(270)
turtle.forward(80)
turtle.setheading(0)
turtle.forward(200)
turtle.end_fill()
turtle.penup()
turtle.color('skyblue')
turtle.goto(100, 40)
turtle.pendown()
turtle.begin_fill()
for a in range(360):
turtle.goto(100 * math.cos(math.radians(a + 1)), 40 + 60 * math.sin(math.radians(a + 1)))
turtle.end_fill()
turtle.penup()
turtle.exitonclick()
就是先画个椭圆,连着画个长方形,涂色后提笔再到上方画个不同颜色的椭圆,是不是很简单~
画太极
最后就是之前蛋糕上的蜡烛,其火焰是太极外形的一半(无内核),接下来展示:
import turtle
turtle.setup(300, 300)
turtle.penup()
turtle.goto(0, -100)
turtle.color('red')
turtle.pendown()
turtle.begin_fill()
turtle.circle(100, 180)
turtle.setheading(0)
turtle.circle(-50, 180)
turtle.setheading(180)
turtle.circle(50, 180)
turtle.end_fill()
turtle.penup()
turtle.color('blue')
turtle.pendown()
turtle.begin_fill()
turtle.setheading(180)
turtle.circle(-100, 180)
turtle.setheading(0)
turtle.circle(-50, 180)
turtle.setheading(180)
turtle.circle(50, 180)
turtle.end_fill()
turtle.penup()
turtle.exitonclick()
半个太极是由一大两小三段半圆圆弧组成的,多试试就知道画弧线会朝哪个方向了~
结束语
今天的太偏向具体数据了,下一篇更新抽象化写绘图程序——用函数封装各种图形画法