python蜡烛图预测 用python画蜡烛_python蜡烛图预测


Python基础图形绘图教学3

  • 绘画蜡烛
  • 绘画椭圆
  • 绘画圆柱
  • 绘画波浪线
  • 绘画正多边形
  • 绘画奇数正多边形内邻点连线图形
  • 绘画正多边形内邻点连线图形
  • 部分图案组合图
  • 结束语


绘画蜡烛

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

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)

python蜡烛图预测 用python画蜡烛_Python_02


这是原先位置的,是不是都超出去了?在不改变函数传入参数的情况下,加上微调:

python蜡烛图预测 用python画蜡烛_python蜡烛图预测_03


两端就这样拐过去了~这样蛋糕上就能容纳更多的 波浪线

绘画正多边形

虽然使用 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蜡烛图预测 用python画蜡烛_python蜡烛图预测_04


把他们拆开后就是这样一堆图形:

python蜡烛图预测 用python画蜡烛_ide_05


好看吧~python绘图就是这样动动手指,绘制自己用手绘画不出来的东西。