如何控制turtle的self._newline()?

1 投票
2 回答
888 浏览
提问于 2025-04-17 13:12

我需要弄清楚如何控制turtle.py中的self._newline()。我是在写Python的曼德尔布罗特集程序时发现这个问题的,当程序开始出现奇怪的情况时;想了解更多细节可以查看为什么turtle会变亮像素?。不过,当我尝试制作一个非常相似的程序来绘制复数的切线时,情况却没有发生……但程序随着时间的推移变得非常慢。

基本上,我有三个问题:

这些程序之间有什么区别导致了这种差异?(这是个思考性的问题)

我该如何激活或停止self._newline()?(这是个必要的主要问题)

我该如何防止self._newline()导致颜色偏差(DSM建议我在turtle.py中插入self._pencolor()的引用,但我不知道该怎么做)?(这不是必须的,但我希望能做到)

即使你不回答中间的问题,我也会非常感激你的意见!

复数切线代码:

import turtle
import math
import cmath
turtle.speed(0)
def bengant(size, onelen):
    turtle.left(90)
    for x in range(-size*onelen, size*onelen+1):
        turtle.up()
        turtle.goto(x, -size*onelen-1)
        turtle.down()
        for y in range(-size*onelen, size*onelen+1):
            c = complex(x*1.0/onelen,y*1.0/onelen)
            k = cmath.tan(c)
            turtle.pencolor(0,math.atan(k.real)/math.pi+1/2,math.atan(k.imag)/math.pi+1/2)
            turtle.forward(1)
bengant(2,100)
x = raw_input("Press Enter to Exit")

2 个回答

0

这些程序之间有什么区别,导致了这个问题的出现?

这个问题出现在很长的单色线条上,而在你的 bengant() 程序中,这种情况并不常见。如果我让它更单色一点(也就是说,把第三个颜色参数改为0,而不是用 math.atan(k.imag) / math.pi + 1/2),问题就会出现:

在这里输入图片描述

通过对Python的turtle库进行监测,可以确认在这些点上你触发了优化条款。

我怎么才能激活/停止 self._newline()?

你不能。问题不是这个优化存在,而是它的实现有问题。不过,正如你在最新的 bengant() 程序中看到的,当涉及更多复杂性时,它就消失了。也许可以向相关人员提交一个带有正确示例的错误报告。

我怎么才能让 self._newline() 不导致颜色偏差?

就你的 benoit() 代码而言,你可以通过将线宽设置为1.5而不是默认的1来有效消除这个问题。这似乎对图像质量影响不大:

在这里输入图片描述

左边是1.0,右边是1.5。不过,你每42个像素的线条会消失。另一种方法是给你的颜色值添加一些随机噪声(小的分数增加),这些噪声对人眼视觉没有影响,但可以防止麻烦的优化被触发。

这是我对你的 benoit() 代码进行修整后的版本,包含了这个修复和一些速度优化:

import turtle

def benoit(onelen):
    turtle.tracer(False)
    turtle.left(90)

    for x in range(-2 * onelen, onelen):
        turtle.up()
        turtle.goto(x, int(-1.5 * onelen) - 1)
        turtle.down()

        for y in range(int(-1.5 * onelen) - 1, int(1.5 * onelen) - 1):
            z = complex(0, 0)
            c = complex(x * 1.0 / onelen, y * 1.0 / onelen)
            g = 0

            for k in range(20):
                z = z * z + c
                if abs(z) > 2:
                    g = 0.2 + 0.8 * (20 - k) / 20
                    break

            turtle.pencolor(0, g, 0)
            turtle.forward(1)

        turtle.update()

    turtle.tracer(True)

turtle.setup(1000, 750)
turtle.hideturtle()
turtle.setundobuffer(None)
turtle.pensize(1.5)  # work around for "42" glitch

benoit(250)

turtle.exitonclick()

这是我对你的 bengant() 代码进行类似处理后的版本:

import math
import cmath
import turtle

def bengant(size, onelen):
    turtle.tracer(False)

    turtle.left(90)

    size_onelen = size * onelen

    for x in range(-size_onelen, size_onelen + 1):
        turtle.up()
        turtle.goto(x, -size_onelen - 1)
        turtle.down()

        for y in range(-size_onelen, size_onelen + 1):
            c = complex(x * 1.0 / onelen, y  * 1.0 / onelen)
            k = cmath.tan(c)
            turtle.pencolor(0, math.atan(k.real) / math.pi + 1/2, math.atan(k.imag) / math.pi + 1/2)
            turtle.forward(1)

        turtle.update()

    turtle.tracer(True)

turtle.hideturtle()

bengant(2, 100)

turtle.exitonclick()
0

我该如何启动/停止 self._newline()?(这是主要问题)

使用 penup 来停止 self.__newline,使用 pendown 来启动它。

参考资料

撰写回答