猫史档案馆


【Python作品分享】海龟画图版单值函数轨迹【作品秀】

用户:e国阳光e国阳光查看:0 回复:0 评论:0 创建时间:2020-12-19T20:51:28


【作品展示】

center_image

 

【作品介绍】

画直角坐标系、单值函数轨迹、直线、点。

 

【作品源代码】

'''初中平面直角坐标系中单调函数轨迹、画直线和打点

@作者  码老师
@微信公众号  学思营 ID:xuesying
@公司  深圳五行星软件有限公司
@日期  2020-12-19

@使用方法
1、导入海龟画图并初始化窗口和画布,例如:
    import turtle as t
    t.setup(600,600)
    t.screensize(400,400)
    t.shape("turtle")
    
2、导入本模块:
    from rcs import *

3、用下面函数:
    build(aTurtle, xUnt = None, yUnt = None, wc = None):
    @aTurtle 一个海龟
    @xUnt  x轴数值与像素对应元组
    @yUnt  y轴数值与像素对应元组
    @wc 自定义坐标元组(llx, lly, urx, ury)
        @llx -- 一个数值, 画布左下角的 x-坐标(像素)
        @lly -- 一个数值, 画布左下角的 y-坐标
        @urx -- 一个数值, 画面右上角的 x-坐标
        @ury -- 一个数值, 画布右上角的 y-坐标
    画平面直角坐标系,例如:
    build(t) #, worldcoordinates=(0,0,400,400))

4、使用模块进行画单调函数轨迹、直线和打点  
(1)画函数轨迹
第一步:定义一个单调函数例如:
        def fun(x):
            return 5*x + 3
第二步:获取x,y的取值范围:
        minx, maxx, miny, maxy = getRange()
第三步(可选):根据x,y的取值范围和函数的实际要求,确定自变量取值范围:
       x1,x2
第四步:调用下面函数:
        trace(aTurtle, x1, x2, fun):
        @aTurtle 一个海龟
        @x1 自变量一端点值
        @x2 自变量另一端点值
        @fun 单调函数
        画函数轨迹,例如:
    #一元一次函数
    def fun(x):
        return 2*x + 1
    trace(t, 50, -50, fun)        

(2)画直线段
第一步:获取x,y的取值范围:
        minx, maxx, miny, maxy = getRange()
第二步:调用下面函数:
        line(aTurtle, x1, y1, x2, y2):
        @aTurtle 一个海龟
        @x1,y1 始点
        @x2,y2 终点
        画直线段,例如画对角线:
        line(t, minx, miny, maxx, maxy)

(3)打圆点
第一步:获取x,y的取值范围:
        minx, maxx, miny, maxy = getRange()
第二步:调用下面函数:
        circularDot(aTurtle, x, y, size=None, *color):
        @aTurtle 一个海龟
        @x,y 坐标
        @size 圆点大小
        @color 圆点颜色
        打圆点,例如下降对角线打点:
    x, y = minx, maxy
    size = 1
    while True:
        if x > maxx or y < miny:
            break
        circularDot(t, x, y, size, "red")
        x += 1
        y -= 1
        size += 1

'''

#导入分数
from fractions import Fraction

#坐标轴线宽
axisWidth = 1
#坐标轴和坐标点颜色
axisColor = "black"
#坐标箭头
axisTurtle = "classic"
#箭头大小 原来四分之一 轮廓线1
axisShapesize = (0.8, 0.8, 1)
#数轴单位(整数)及其对应的像素大小(整数) 1对应10像素
xUnit = [1, 20]
yUnit = [1, 20]
#方格线宽
squareWidth = 1
#方格线色 浅蓝
squareColor = "#EFEFFF"
#数点线长
markLen = 5
#数字字体
markFont=("Arial", 8, "normal")
#坐标系,调用build后才有值
worldcoordinates = None


#检测数轴单位
def __checkUnit(unt):
    if unt != None and len(unt) == 2:
        return isinstance(unt[0],int) and isinstance(unt[0],int)
    return False



#建立直角坐标系
def build(aTurtle, xUnt = None, yUnt = None, wc = None):
    '''按初中课本使用的直角坐标系绘图
    @aTurtle 一个海龟
    @xUnt  x轴数值与像素对应元组
    @yUnt  y轴数值与像素对应元组
    @wc 自定义坐标元组(llx, lly, urx, ury)
        @llx -- 一个数值, 画布左下角的 x-坐标(像素)
        @lly -- 一个数值, 画布左下角的 y-坐标
        @urx -- 一个数值, 画面右上角的 x-坐标
        @ury -- 一个数值, 画布右上角的 y-坐标'''
    #保持海龟原来的参数后设置参数
    speed = aTurtle.speed()
    aTurtle.speed(0)
    width = aTurtle.pensize()
    pencolor = aTurtle.pencolor()
    shape = aTurtle.shape()
    shapesize = aTurtle.shapesize()
    isdown = aTurtle.isdown()
    pos = aTurtle.pos()
    heading =aTurtle.heading()

    #数量与像素的对应关系
    if __checkUnit(xUnt):
        xUnit[0] = xUnt[0]
        xUnit[1] = xUnt[1]
    if __checkUnit(yUnt):
        yUnit[0] = yUnt[0]
        yUnit[1] = yUnt[1]

    global worldcoordinates

    #自定义坐标
    if wc != None and len(wc) == 4:
        worldcoordinates = wc
        aTurtle.setworldcoordinates(*worldcoordinates) #自定义坐标系
    else:
        temp = aTurtle.screensize()
        worldcoordinates = (-temp[0]/2,-temp[1]/2,temp[0]/2,temp[1]/2)

    #定坐标方向
    xh = worldcoordinates[0] < worldcoordinates[2]
    if xh:  #True从左到右
        x1,x2 = int(worldcoordinates[0]), int(worldcoordinates[2])
    else:
        x1,x2 = int(worldcoordinates[2]), int(worldcoordinates[0])
    yh = worldcoordinates[1] < worldcoordinates[3]
    if yh:  #True从下到上
        y1,y2 = int(worldcoordinates[1]), int(worldcoordinates[3])
    else:
        y1,y2 = int(worldcoordinates[3]), int(worldcoordinates[1])


    #画方格线
    #画与y轴平行的线
    if isdown:
        aTurtle.up()
    for i in range(-xUnit[1], x1, -xUnit[1]):
        aTurtle.pencolor(squareColor)
        aTurtle.pensize(squareWidth)
        aTurtle.setpos(i,y1)
        aTurtle.down()
        aTurtle.sety(y2)
        aTurtle.up()
        aTurtle.sety(0)
        aTurtle.down()        
        aTurtle.pencolor(axisColor)
        aTurtle.pensize(axisWidth)
        aTurtle.sety(markLen)
        aTurtle.up()
        if yh:   #标x数字
            aTurtle.sety(-markLen-markFont[1])  #还要下降字体高度
        else:
            aTurtle.sety(-markLen//2)           #无需下降字体高度
        aTurtle.write(i//xUnit[1]*xUnit[0], align="center", font = markFont)        
    for i in range(xUnit[1], x2, xUnit[1]):
        aTurtle.pencolor(squareColor)
        aTurtle.pensize(squareWidth)
        aTurtle.setpos(i,y1)
        aTurtle.down()
        aTurtle.sety(y2)
        aTurtle.up()
        aTurtle.sety(0)
        aTurtle.down()        
        aTurtle.pencolor(axisColor)
        aTurtle.pensize(axisWidth)
        aTurtle.sety(markLen)
        aTurtle.up()
        if yh:
            aTurtle.sety(-markLen-markFont[1])
        else:
            aTurtle.sety(-markLen//2)
        aTurtle.write(i//xUnit[1]*xUnit[0], align="center", font = markFont)
    #画与x轴平行的线
    for i in range(-yUnit[1], y1, -yUnit[1]):
        aTurtle.pencolor(squareColor)
        aTurtle.pensize(squareWidth)
        aTurtle.setpos(x1, i)
        aTurtle.down()
        aTurtle.setx(x2)
        aTurtle.up()
        aTurtle.setx(0)
        aTurtle.down()        
        aTurtle.pencolor(axisColor)
        aTurtle.pensize(axisWidth)
        aTurtle.setx(markLen)
        aTurtle.up()
        if yh:  #标y数字
            aTurtle.setpos(-markLen//2, i-markFont[1]//2) #下降字体高度一半
        else:
            aTurtle.setpos(-markLen//2, i+markFont[1]//2)
        if xh:  
            aTurtle.write(i//yUnit[1]*yUnit[0], align="right", font = markFont)
        else:
            aTurtle.write(i//yUnit[1]*yUnit[0], font = markFont)            
    for i in range(yUnit[1], y2, yUnit[1]):
        aTurtle.pencolor(squareColor)
        aTurtle.pensize(squareWidth)
        aTurtle.setpos(x1, i)
        aTurtle.down()
        aTurtle.setx(x2)
        aTurtle.up()
        aTurtle.setx(0)
        aTurtle.down()        
        aTurtle.pencolor(axisColor)
        aTurtle.pensize(axisWidth)
        aTurtle.setx(markLen)
        aTurtle.up()
        if yh:
            aTurtle.setpos(-markLen//2, i-markFont[1]//2)
        else:
            aTurtle.setpos(-markLen//2, i+markFont[1]//2)
        if xh:
            aTurtle.write(i//yUnit[1]*yUnit[0], align="right", font = markFont)
        else:
            aTurtle.write(i//yUnit[1]*yUnit[0], font = markFont)

    #画坐标
    aTurtle.pencolor(axisColor)
    aTurtle.pensize(axisWidth)
    aTurtle.shape(axisTurtle)
    aTurtle.shapesize(*axisShapesize)
    aTurtle.up()
    aTurtle.setpos(x1, 0)
    aTurtle.down()
    aTurtle.setx(x2)
    if xh:
        aTurtle.seth(0)
    else:
        aTurtle.seth(180)
    aTurtle.stamp()
    aTurtle.up()
    if yh:
        aTurtle.sety(-markLen-markFont[1])
    else:
        aTurtle.sety(-markLen//2)
    aTurtle.write('x', align="center", font = markFont)
    aTurtle.setpos(0, y1)
    aTurtle.down()
    aTurtle.sety(y2)
    if yh:
        if xh:
            aTurtle.seth(90)
        else:
            aTurtle.seth(-90)
    else:
        if xh:
            aTurtle.seth(90)
        else:
            aTurtle.seth(-90)
    aTurtle.stamp()
    aTurtle.up()
    if yh:
        aTurtle.setpos(-markLen//2, y2-markFont[1])
    else:
        aTurtle.setx(-markLen//2)
    if xh:
        aTurtle.write('y', align="right", font = markFont)
    else:
        aTurtle.write('y', font = markFont)

    #标注原点
    if yh:
        aTurtle.setpos(-markLen//2, -markLen-markFont[1])
    else:
        aTurtle.setpos(-markLen//2, -markLen//2)
    if xh:
        aTurtle.write(0, align="right", font = markFont)
    else:
        aTurtle.write(0, font = markFont)
        

    #恢复海龟原来的设置参数
    aTurtle.speed(speed)
    aTurtle.shape(shape)
    aTurtle.pensize(width)
    aTurtle.pencolor(pencolor)
    aTurtle.shapesize(*shapesize)
    aTurtle.setpos(*pos)
    aTurtle.seth(heading)
    if isdown:
        aTurtle.down()

#检查是否已经初始化
def __checkBuild():
    if worldcoordinates == None:
        print("还没有画坐标,请调用build(aTurtle, xUnt = None, yUnt = None, worldcoordinates = None)函数画坐标")
        return False
    else:
        return True

#屏幕上进1像素实际的值之间的转换
def __pixchange():
    #屏幕上进1像素实际的值之间的转换
    dx, udx, dy, udy = Fraction(*xUnit), Fraction(xUnit[1], xUnit[0]), Fraction(*yUnit), Fraction(yUnit[1], yUnit[0])
    #x坐标作图范围
    if worldcoordinates[0] < worldcoordinates[2]:
        minx, maxx = dx * worldcoordinates[0], dx * worldcoordinates[2]
    else:
        minx, maxx = dx * worldcoordinates[2], dx * worldcoordinates[0]
    #y坐标作图范围
    if worldcoordinates[1] < worldcoordinates[3]:
        miny, maxy = dy * worldcoordinates[1], dy * worldcoordinates[3]
    else:
        miny, maxy = dy * worldcoordinates[3], dy * worldcoordinates[1]
    return dx, udx, dy, udy, minx, maxx, miny, maxy

#函数轨迹
def trace(aTurtle, x1, x2, fun):
    '''函数轨迹
    @aTurtle 一个海龟
    @x1 自变量一端点值
    @x2 自变量另一端点值
    @fun 单调函数'''

    #自变量检查
    if x1 == x2:
        print("自变量不可以相等")
        return False        

    #检查是否已经画坐标
    if not __checkBuild():        
        return False
    
    #保持海龟落笔状态
    isdown = aTurtle.isdown()
    speed = aTurtle.speed()
    aTurtle.speed(0)
    pos = aTurtle.pos()
    if isdown:
        aTurtle.up()
    
    if x1 > x2:    #交换自变量
        temp = x1
        x1 = x2
        x2 = temp

    #屏幕上进1像素实际的值之间的转换
    dx, udx, dy, udy, minx, maxx, miny, maxy  =  __pixchange()


    if x2 <= minx or x1 >= maxx:
        print("自变量不在%s到%s范围内!" % (str(minx), str(maxx)))
        return False
    if x1 < minx:
        x1 = minx
    if x2 > maxx:
        x2 = maxx
        

    #起点
    x = x1
    y = fun(x1)
    if y >= miny and y<= maxy:
        aTurtle.setpos(udx*x, udy*y)
        aTurtle.down()
        

    #描图
    while True:
        x += dx
        if x > x2: #过了终点
            break
        y = fun(x)
        if y >= miny and y<= maxy:
            aTurtle.setpos(udx*x, udy*y)
            if not aTurtle.isdown():
                aTurtle.down()
        else:
            if aTurtle.isdown():
               aTurtle.setpos(udx*x, udy*y) 
            aTurtle.up()

    if aTurtle.isdown():
        aTurtle.up()
    aTurtle.setpos(*pos)
    aTurtle.speed(speed)
    #恢复下笔状态 
    if isdown:
        aTurtle.down()

    return True

#作图范围
def getRange():
    '''作图范围
    @return x坐标最小值,x坐标最大值,y坐标最小值,y坐标最大值'''
    
    #检查是否已经画坐标
    if not __checkBuild():        
        return None    

    #屏幕上进1像素实际的值之间的转换
    dx, udx, dy, udy, minx, maxx, miny, maxy  =  __pixchange()
    return minx, maxx, miny, maxy

#作图范围字符串
def __rangestr(minx, maxx, miny, maxy):
    return "%s≤x≤%s,%s≤y≤%s" % (str(minx),str(maxx),str(miny),str(maxy))
    
#画线段
def line(aTurtle, x1, y1, x2, y2):
    '''画线段
    @aTurtle 一个海龟
    @x1,y1 始点
    @x2,y2 终点'''

    #检查是否已经画坐标
    if not __checkBuild():        
        return False    

    #屏幕上进1像素实际的值之间的转换
    dx, udx, dy, udy, minx, maxx, miny, maxy  =  __pixchange()

    if min(x1, x2) < minx or max(x1, x2) > maxx or min(y1, y2) < miny or max(y1, y2) > maxy:
        print("有端点不在作图范围(%s)内!" % __rangestr(minx, maxx, miny, maxy))
        return False   

    #保持海龟落笔状态
    isdown = aTurtle.isdown()
    pos = aTurtle.pos()
    speed = aTurtle.speed()
    aTurtle.speed(0)
    if isdown:
        aTurtle.up()

    aTurtle.setpos(udx*x1, udy*y1)
    aTurtle.down()
    aTurtle.setpos(udx*x2, udy*y2)
    aTurtle.up()
    aTurtle.setpos(*pos)
    aTurtle.speed(speed)
    if isdown:
        aTurtle.down()
    return True

#打圆点
def circularDot(aTurtle, x, y, size=None, *color):
    '''打点
    @aTurtle 一个海龟
    @x,y  坐标
    @size 圆点大小
    @color 圆点颜色'''

    #检查是否已经画坐标
    if not __checkBuild():        
        return False    

    #屏幕上进1像素实际的值之间的转换
    dx, udx, dy, udy, minx, maxx, miny, maxy  =  __pixchange()

    if x< minx or x > maxx or y < miny or y > maxy:
        print("该点点不在作图范围(%s)内!" % __rangestr(minx, maxx, miny, maxy))
        return False
    
    isdown = aTurtle.isdown()
    pos = aTurtle.pos()
    speed = aTurtle.speed()
    aTurtle.speed(0)
    if isdown:
        aTurtle.up()
    aTurtle.setpos(udx*x, udy*y)
    if color == None:
        aTurtle.dot(size)
    else:
        aTurtle.dot(size, *color)

    aTurtle.setpos(*pos)
    aTurtle.speed(speed)
    if isdown:
        aTurtle.down()
    return True    
    

if __name__ == "__main__":
    import turtle as t
    t.setup(600,600)
    t.screensize(400,400)
    t.shape("turtle")
    build(t) #, worldcoordinates=(0,0,400,400))
    #一元一次函数
    def fun1(x):
        return 2*x + 1
    trace(t, 50, -50, fun1)
    #一元二次函数
    def fun2(x):
        return x**2 + 2*x + 2
    trace(t, 50, -50, fun2)
    #画圆
    def fun3(x):
        return (5**2 - x**2)**0.5
    trace(t, 5, -5, fun3)
    def fun4(x):
        return -(5**2 - x**2)**0.5
    trace(t, 5, -5, fun4)
    #画对角线
    minx, maxx, miny, maxy = getRange()
    line(t, minx, miny, maxx, maxy)
    #打点对角线
    x, y = minx, maxy
    size = 1
    while True:
        if x > maxx or y < miny:
            break
        circularDot(t, x, y, size, "red")
        x += 1
        y -= 1
        size += 1
        
    t.mainloop()

 

【提示】

部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:

https://python.codemao.cn


回复

上一页1 页 / 共 0下一页