【Python绘图】绘图常见的构成元素3

🌈据说,看我文章时 关注、点赞、收藏帅哥美女们 心情都会不自觉的好起来。

前言:
🧡作者简介:大家好我是 user_from_future ,意思是 “ 来自未来的用户 ” ,寓意着未来的自己一定很棒~
✨个人主页:点我直达,在这里肯定能找到你想要的~
👍专栏介绍:Python绘图 ,一个专注于分享绘图案例与教学的专栏~

专栏文章直链:
【Python绘图】绘图常见的构成元素2
【Python绘图】绘图常见的构成元素1
【Python绘图】学习绘图第一步,先要知道哪些操作是常用的
【Python绘图】朋友过生日不知道送什么?免费的蛋糕送给他
人生苦短,我用python

绘画蜡烛

先从之前的蛋糕案例中搞几个已经写好的图形。
根据蜡烛底部的中心坐标、蜡烛的高度宽度绘制蜡烛,以蜡烛的宽度作为烛焰的直径:

def draw_candle(location, width, height):
    """
    画蜡烛。
    :param location: 蜡烛底部中心坐标
    :param width: 蜡烛宽度
    :param height: 蜡烛高度
    """
    color = turtle.color()
    angle = turtle.heading()
    turtle.penup()
    turtle.color('skyblue')
    turtle.setheading(0)
    turtle.goto(*location)
    turtle.pendown()
    turtle.begin_fill()
    turtle.forward(width / 2)
    turtle.setheading(90)
    turtle.forward(height)
    turtle.setheading(180)
    turtle.forward(width)
    turtle.setheading(270)
    turtle.forward(height)
    turtle.setheading(0)
    turtle.forward(width / 2)
    turtle.end_fill()
    turtle.penup()
    turtle.setheading(90)
    turtle.forward(height)
    turtle.setheading(20)
    turtle.color('red')
    turtle.pendown()
    turtle.begin_fill()
    turtle.circle(width / 2, 180)
    turtle.setheading(20)
    turtle.circle(-width / 4, 180)
    turtle.setheading(200)
    turtle.circle(width / 4, 180)
    turtle.end_fill()
    turtle.penup()
    turtle.color(*color)
    turtle.goto(*location)
    turtle.setheading(angle)

这个还是很简单,一个长方形和一个半太极就完成了。

绘画椭圆

这里就是通过椭圆中心坐标进行绘图的,比从边开始绘图方便了点,易于管理:

def draw_oval(location, width, height, fill=True, color='#000000'):
    """
    画椭圆。
    :param location: 椭圆中心坐标
    :param width: 椭圆长轴(横向)
    :param height: 椭圆短轴(纵向)
    :param fill: 是否填充
    :param color: 椭圆颜色
    """
    assert width >= height, ValueError('目前只能长轴是 x 轴,即 width >= height (width == height 时是圆)!')
    a = width / 2
    b = height / 2
    color_old = turtle.color()
    angle = turtle.heading()
    turtle.color(color)
    turtle.penup()
    turtle.goto(*location)
    turtle.setheading(0)
    turtle.forward(width / 2)
    turtle.setheading(90)
    turtle.pendown()
    if fill:
        turtle.begin_fill()
    if width < 180:  # 通过椭圆直角坐标方程计算描点绘画
        for x in range(width // 2, width // -2, -1):  # 以 y = location[1] 的单位上半部分描点
            y = location[1] + (((a ** 2 - x ** 2) * b ** 2) / a ** 2) ** 0.5
            turtle.goto(x, y)
        for x in range(width // -2, width // 2 + 1):  # 以 y = location[1] 的单位下半部分描点
            y = location[1] - (((a ** 2 - x ** 2) * b ** 2) / a ** 2) ** 0.5
            turtle.goto(x, y)
    else:  # 通过椭圆极坐标方程计算描点绘画
        for ang in range(360):
            turtle.goto(width / 2 * math.cos(math.radians(ang + 1)), location[1] + height / 2 * math.sin(math.radians(ang + 1)))
    if fill:
        turtle.end_fill()
    turtle.penup()
    turtle.color(*color_old)
    turtle.goto(*location)
    turtle.setheading(angle)

绘画圆柱

这里以底部椭圆的中心坐标作为起始点,比椭圆多两个参数,多一个圆柱高度和圆柱侧面填充颜色,操作也就是先画底部椭圆,在画侧边长方形,最后上方再盖一层一模一样的椭圆:

def draw_cylinder(location, width, height, altitude, fill=True, color1='#000000', color2='#000000'):
    """
    画椭圆柱。
    :param location: 底部椭圆中心坐标
    :param width: 底部椭圆长轴(横向)
    :param height: 底部椭圆短轴(纵向)
    :param altitude: 椭圆柱高度
    :param fill: 是否填充
    :param color1: 椭圆柱面绘图颜色
    :param color2: 椭圆柱顶绘图颜色
    """
    color_old = turtle.color()
    angle = turtle.heading()
    draw_oval(location, width, height, fill=fill, color=color1)
    turtle.penup()
    turtle.color(color1)
    turtle.goto(*location)
    turtle.setheading(0)
    turtle.forward(width / 2)
    turtle.pendown()
    if fill:
        turtle.begin_fill()
        turtle.setheading(90)
        turtle.forward(altitude)
        turtle.setheading(180)
        turtle.forward(width)
        turtle.setheading(270)
        turtle.forward(altitude)
        turtle.setheading(0)
        turtle.forward(width)
        turtle.end_fill()
    turtle.penup()
    location = (location[0], location[1] + altitude)
    draw_oval(location, width, height, fill=fill, color=color2)
    turtle.penup()
    turtle.color(*color_old)
    turtle.goto(*location)
    turtle.setheading(angle)

绘画波浪线

其实就是在画三角函数,设置一下画笔宽度和起伏程度,计算波浪形状改变比例:

def draw_wave(location, width, height, space, pensize=10, color='#000000', towards='right'):
    """
    画波浪线。
    :param location: 波浪线起点(中心点)
    :param width: 波浪线总宽度
    :param height: 波浪线高度
    :param space: 波浪间距
    :param pensize: 波浪粗细
    :param color: 波浪颜色
    :param towards: 破浪线朝向
    """
    assert towards.lower() in ['left', 'right'], '方向只能是 left向左 或 right向右 !'
    color_old = turtle.color()
    angle = turtle.heading()
    thickness = turtle.pensize()
    turtle.color(color)
    turtle.penup()
    turtle.goto(*location)
    turtle.pensize(pensize)
    turtle.pendown()
    if towards.lower() == 'right':
        turtle.setheading(0)
    else:
        turtle.setheading(180)
    for x in range(width):
        turtle.goto(location[0] + x, location[1] + height / 2 * math.sin(math.radians(x * 180 / space)))
    turtle.penup()
    turtle.color(*color_old)
    turtle.pensize(thickness)
    turtle.goto(*location)
    turtle.setheading(angle)

用在蛋糕上有点简陋,毕竟蛋糕上圆柱侧面所显示的是个扇形弧面,应该让图像两边的y值按比例扩大一下,接下来就是经过修改后的函数:

def draw_wave(location, width, height, space, pensize=10, color='#000000', towards='right'):
    """
    画波浪线。
    :param location: 波浪线起点(中心点)
    :param width: 波浪线总宽度
    :param height: 波浪线高度
    :param space: 波浪间距
    :param pensize: 波浪粗细
    :param color: 波浪颜色
    :param towards: 破浪线朝向
    """
    assert towards.lower() in ['left', 'right'], '方向只能是 left向左 或 right向右 !'
    color_old = turtle.color()
    angle = turtle.heading()
    thickness = turtle.pensize()
    turtle.color(color)
    turtle.penup()
    turtle.goto(location[0], location[1] + height)
    turtle.pensize(pensize)
    turtle.pendown()
    if towards.lower() == 'right':
        turtle.setheading(0)
    else:
        turtle.setheading(180)
    for x in range(width):
        turtle.goto(location[0] + x, location[1] + height / 2 * math.sin(math.radians(x * 180 / space)) + height * abs(x - width / 2) / width * 2)
    turtle.penup()
    turtle.color(*color_old)
    turtle.pensize(thickness)
    turtle.goto(*location)
    turtle.setheading(angle)

在这里插入图片描述
这是原先位置的,是不是都超出去了?在不改变函数传入参数的情况下,加上微调:
在这里插入图片描述
两端就这样拐过去了~这样蛋糕上就能容纳更多的 波浪线 奶油条了。

绘画正多边形

虽然使用 turtle.circle(radius, extent, steps) 也能画正多边形,但是他是按外接圆半径计算的,这里用边长来绘画:

def draw_polygon_by_point(point, radius, rotate, side, fill=True):
    """
    按起始顶点和边长绘制圆内正多边形。
    :param point: 顶点位置
    :param radius: 边长
    :param rotate: 中心顺时针旋转
    :param side: 边数
    :param fill: 是否填充
    """
    assert side > 2 and isinstance(side, int), ValueError('边数必须是大于2的正整数!')
    turtle.penup()
    turtle.setheading((180 * (side - 2) / side) / 2 - 90)  # 绝对数值对称
    turtle.right(rotate)  # 初始中心旋转
    turtle.goto(point[0], point[1])
    turtle.pendown()
    if fill:
        turtle.begin_fill()
    for angle in range(side):
        turtle.forward(radius)
        turtle.right(180 - (180 * (side - 2) / side))
    if fill:
        turtle.end_fill()
    turtle.penup()
    turtle.setheading(0)  # 恢复到水平向右的方向

这个包含的初始旋转和中心顺时针旋转,能自动让顶点位于正上方(在不使用中心旋转的情况下)

绘画奇数正多边形内邻点连线图形

上次绘画的方式是从边上某点就开始绘画了,这次统一从中心点来看待这些图形:

def draw_odd_shape(location, radius, rotate, side, fill=True):
    """
    按外接圆圆心和半径绘制圆内正多边形顶点连线图(奇数边数)。
    :param location: 圆心位置
    :param radius: 半径长度
    :param rotate: 中心顺时针旋转
    :param side: 边数
    :param fill: 是否填充
    """
    length = 2 * radius * math.sin(math.radians(180 * (side - 2) / side + (45 if side == 4 else 0)))  # 计算任意两间隔顶点间的距离
    turtle.penup()
    turtle.setheading(90)  # 先将初始顶点设置于正上方
    turtle.right(rotate)  # 初始中心旋转
    turtle.goto(location[0], location[1])
    turtle.forward(radius)  # 此处到达最上方顶点
    turtle.right(90 + 2 * 180 / (side if side != 4 else 8))  # 倾斜方便绘制第一条直线
    turtle.pendown()
    if fill:
        turtle.begin_fill()
    for angle in range(side):
        turtle.forward(length)
        turtle.right(4 * 180 / (side if side != 4 else 8))
    if fill:
        turtle.end_fill()
    turtle.penup()
    turtle.setheading(90)  # 恢复到垂直向上的方向
    turtle.goto(location[0], location[1])

绘画正多边形内邻点连线图形

def draw_polygon_by_center(location, radius, rotate, side, fill=True):
    """
    按外接圆圆心和半径绘制圆内正多边形最近间隔顶点连线图。
    :param location: 圆心位置
    :param radius: 半径长度
    :param rotate: 中心顺时针旋转
    :param side: 边数
    :param fill: 是否填充
    """
    assert side > 2 and isinstance(side, int), ValueError('边数必须是大于2的正整数!')
    if side < 5 or side % 2:  # 边数小于5,或者是奇数边数时可以一次性画完
        draw_odd_shape(location, radius, rotate, side, fill)
    else:  # 偶数边数时要分两个小形状变换角度画两次
        '''
            正多边形内间最远隔点连线图:
            draw_polygon_by_center(location, radius, rotate, side // 2, fill)
            draw_polygon_by_center(location, radius, rotate + 360 / side, side // 2, fill)
        '''
        location = (location[0], location[1] + radius)
        draw_polygon_by_point(location, 2 * radius * math.sin(math.radians(180 * (side - 2) / side + (45 if side == 4 else 0))), rotate, side // 2, fill)
        turtle.goto(location[0], location[1] - radius)  # 回到中心
        turtle.setheading(90 - (rotate + 360 / side))  # 向右上角出发
        turtle.forward(radius)  # 前进到右上角顶点
        location = turtle.position()  # 获取右上角顶点坐标
        turtle.back(radius)  # 返回中心
        draw_polygon_by_point(location, 2 * radius * math.sin(math.radians(180 * (side - 2) / side + (45 if side == 4 else 0))), rotate + 360 / side, side // 2, fill)

在这函数中,会自动判断边数是不是奇数,奇数或者边过少,则直接调用画奇数的函数,否则自动绘画两个正多边形并自动旋转。

部分图案组合图

首先上场的是正三边形到正十八边形内邻点连线图形,之前也发过一个有更多边形的红色组合,这里用黄色的显示:
在这里插入图片描述
把他们拆开后就是这样一堆图形:
在这里插入图片描述
好看吧~python绘图就是这样动动手指,绘制自己用手绘画不出来的东西。

结束语

下两篇看情况能不能更新两个“特殊图形”,就基本上只发代码了,图发了就怕没法公开了…🤣

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值