Turtle Graphics are incompatible with gmpy

Mensanator mensanator at aol.com
Wed Aug 5 01:49:16 EDT 2009


I hadn't noticed this before, but the overhaul of Turtle Graphics
dating
back to 2.6 has been broken as far as gmpy is concerned.

I hadn't noticed because I usually have tracing turned off (tracing
off
takes 3-4 seconds, tracing on takes 6-7 minutes).

In 3.1, tracing is now a screen attribute, not a turtle atribute.
I have no idea why

  tooter = turtle.Turtle()
  tooter.tracer(False)

doesn't give me an error (I thought silent errors were a bad thing).

Had to change to

  tooter = turtle.Turtle()
  tooter.screen.tracer(False) # tracer now a screen attribute

to turn tracing off in 3.1.

Naturally, having tracing on caused my program to crash. The 2.6
version
seemed to work, but only because turning off tracing as a turtle
attribute
works in 2.6.

So I turned it back on and it crashed too.

2.5 worked okay.

The reason is that code in turtle.py was chabged from

v2.5
        if self._drawing:
            if self._tracing:
                dx = float(x1 - x0)
                dy = float(y1 - y0)
                distance = hypot(dx, dy)
                nhops = int(distance)

to

v3.1
       if self._speed and screen._tracing == 1:
            diff = (end-start)
            diffsq = (diff[0]*screen.xscale)**2 + (diff[1]
*screen.yscale)**2
            nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)
*self._speed))

Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy
floating point). Otherwise, you get

Traceback (most recent call last):
  File "K:\user_python26\turtle\turtle_xy_Py3.py", line 95, in
<module>
    tooter.goto(the_coord)
  File "C:\Python31\lib\turtle.py", line 1771, in goto
    self._goto(Vec2D(*x))
  File "C:\Python31\lib\turtle.py", line 3165, in _goto
    nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
ValueError: mpq.pow fractional exponent, inexact-root

So when using gmpy, you have to convert the .mpz to int before calling
turtle
functions. (if tracing is on).

demo code (fixed code commented out)

import gmpy

##   (even) hi----|
##                |
##                lo (odd)
## or
##
##   (even) lo
##           |
##           |
##           ----hi (odd)
##
##
##
##

import turtle

tooter = turtle.Turtle()

tooter.hideturtle()
tooter.speed('fast')
turtle.update()
# make tracer false and it works
#tooter.screen.tracer(False) # tracer now a screen attribute
tooter.penup()
tooter.color('black')

s = ['1','0']
while len(s[0])<10000:
    s = [''.join(s), s[0]]


origin = [0,0]
if s[0] == '0':
  tooter.goto(origin)
  tooter.dot(1)
if s[1] == '0':
  tooter.goto([1,0])
  tooter.dot(1)

print(len(s[0]))

for i,j in enumerate(s[0]):
  the_coord=[]
  cur_root = gmpy.sqrt(i)
  lo__root = gmpy.sqrt(i)**2
  hi__root = ((gmpy.sqrt(i)+1)**2)
##  cur_root = int(gmpy.sqrt(i))
##  lo__root = int(gmpy.sqrt(i)**2)
##  hi__root = int(((gmpy.sqrt(i)+1)**2))

  if hi__root%2==0:
    side = 'northeast'
  else:
    side = 'southwest'

  elbow = (hi__root - lo__root)//2 + lo__root + 1

  if i>= elbow:

    side_len = i - elbow
    elbow_plus = True
  else:
    side_len = elbow - i
    elbow_plus = False

  if side == 'northeast':
    elbow_offset = [(gmpy.sqrt(elbow)-1)//2 +1,-((gmpy.sqrt(elbow)-1)//
2) +1]
  else:
    elbow_offset = [-((gmpy.sqrt(elbow)-1)//2 +1),((gmpy.sqrt
(elbow)-1)//2 +1)]
##  if side == 'northeast':
##    elbow_offset = [int((gmpy.sqrt(elbow)-1)//2 +1),-int(((gmpy.sqrt
(elbow)-1)//2) +1)]
##  else:
##    elbow_offset = [-int(((gmpy.sqrt(elbow)-1)//2 +1)),int
(((gmpy.sqrt(elbow)-1)//2 +1))]

  elbow_coord = [origin[0]+elbow_offset[0],origin[1]+elbow_offset[1]]

  if i != hi__root and i != lo__root:
    if i == elbow:
      the_coord = elbow_coord
    else:
      if elbow_plus:
        if side == 'northeast':
          the_coord = [elbow_coord[0]-side_len,elbow_coord[1]]
        else:
          the_coord = [elbow_coord[0]+side_len,elbow_coord[1]]
      else:
        if side == 'northeast':
          the_coord = [elbow_coord[0],elbow_coord[1]+side_len]
        else:
          the_coord = [elbow_coord[0],elbow_coord[1]-side_len]
  else:
    if i % 2 == 0:  # even square
      n = gmpy.sqrt(i)//2 - 1
##      n = int(gmpy.sqrt(i)//2) - 1
      the_coord = [-n, -n-1]
    else:
      n = (gmpy.sqrt(i)-1)//2 - 1
##      n = int((gmpy.sqrt(i)-1)//2) - 1
      the_coord = [1+n, 1+n]
  if j == '0':
    tooter.goto(the_coord)
    tooter.dot(2)
print('done')

turtle.update()
turtle.done()
print('done')



More information about the Python-list mailing list