タートルの関連する使用法については、["Pythonグラフィックス描画ライブラリタートルの中国の開発ドキュメントと例"](https://blog.csdn.net/A757291228/article/details/105884899)を参照してください。
この記事はタートルライブラリの実現の分析ですが、パイソンTKライブラリは含まれていません。
turtleでは、forwardまたはfd関数を使用して直進します。このマシンにturtleライブラリをインストールした後、turtle.pyファイルは次のディレクトリにあります。
入り口から従来の方法でタートルライブラリの基本的な実装を調べることから始めましょう。新しいタートルオブジェクトを作成します。
tt=Turtle()
ファイルでクラスTurtleを見つけます。
classTurtle(RawTurtle):"""RawTurtle auto-creating(scrolled) canvas.
When a Turtle object is created or a function derived from some
Turtle method is called a TurtleScreen object is automatically created."""
_ pen = None
_ screen = None
def __init__(self,
shape=_CFG["shape"],
undobuffersize=_CFG["undobuffersize"],
visible=_CFG["visible"]):if Turtle._screen is None:
Turtle._screen =Screen()
RawTurtle.__init__(self, Turtle._screen,
shape=shape,
undobuffersize=undobuffersize,
visible=visible)
コメントから、このクラスは自動的に TurtleScreen
オブジェクトと canvas
を作成することがわかります。これは、 __init__
メソッドのコードプロセスにあります。その後、 RawTurtle
の __init __
が呼び出され、タートルのアニメーション部分が作成されます。次のように:
screens =[]
def __init__(self, canvas=None,
shape=_CFG["shape"],
undobuffersize=_CFG["undobuffersize"],
visible=_CFG["visible"]):ifisinstance(canvas, _Screen):
self.screen = canvas
elif isinstance(canvas, TurtleScreen):if canvas not in RawTurtle.screens:
RawTurtle.screens.append(canvas)
self.screen = canvas
elif isinstance(canvas,(ScrolledCanvas, Canvas)):for screen in RawTurtle.screens:if screen.cv == canvas:
self.screen = screen
breakelse:
self.screen =TurtleScreen(canvas)
RawTurtle.screens.append(self.screen)else:
raise TurtleGraphicsError("bad canvas argument %s"% canvas)
screen = self.screen
TNavigator.__init__(self, screen.mode())
TPen.__init__(self)
screen._turtles.append(self)
self.drawingLineItem = screen._createline()
self.turtle =_TurtleImage(screen, shape)
self._poly = None
self._creatingPoly = False
self._fillitem = self._fillpath = None
self._shown = visible
self._hidden_from_screen = False
self.currentLineItem = screen._createline()
self.currentLine =[self._position]
self.items =[self.currentLineItem]
self.stampItems =[]
self._undobuffersize = undobuffersize
self.undobuffer =Tbuffer(undobuffersize)
self._update()
タートルオブジェクトを作成した後、forward関数を呼び出してラインセグメントを描画します。
タートルファイルを開き、関数定義の一般的な形式に従って、フォワード関数の定義を照会します。
コメントから、forward | fdを使用して関数を呼び出すことができ、パラメーターは距離を渡すことであることがわかります。具体的な使用方法については、記事の冒頭に記されている記事を参照してください。ここではあまり説明がありません。
forward関数の下部で、_goメソッドが呼び出されていることがわかります: self._go(distance)
。 _goメソッドを表示します。
def _go(self, distance):"""move turtle forward by specified distance"""
ende = self._position + self._orient * distance
self._goto(ende)
goメソッドでは、距離が渡され、endeが self._position + self._orient * distance
に割り当てられます。まず、 position、_orient、およびdistanceのメンバーが何であるかを理解します。
_ goメソッドはTNavigatorクラスにあります。TNavigatorのinitメソッドでは、resetメソッドが使用されます。resetメソッドには、_positionおよび_orientの初期化があります。
def reset(self):"""reset turtle to its initial values
Will be overwritten by parent class"""
self._position =Vec2D(0.0,0.0)
self._orient = TNavigator.START_ORIENTATION[self._mode]
Vec2Dをもう一度見てみましょう。
classVec2D(tuple):"""A 2 dimensional vector class, used as a helper classfor implementing turtle graphics.
May be useful for turtle graphics programs also.
Derived from tuple, so a vector is a tuple!Provides(for a, b vectors, k number):
a+b vector addition
a-b vector subtraction
a*b inner product
k*a and a*k multiplication with scalar
| a| absolute value of a
a.rotate(angle) rotation
"""
def __new__(cls, x, y):return tuple.__new__(cls,(x, y))
def __add__(self, other):returnVec2D(self[0]+other[0], self[1]+other[1])
def __mul__(self, other):ifisinstance(other, Vec2D):return self[0]*other[0]+self[1]*other[1]returnVec2D(self[0]*other, self[1]*other)
def __rmul__(self, other):ifisinstance(other, int) or isinstance(other, float):returnVec2D(self[0]*other, self[1]*other)
def __sub__(self, other):returnVec2D(self[0]-other[0], self[1]-other[1])
def __neg__(self):returnVec2D(-self[0],-self[1])
def __abs__(self):return(self[0]**2+ self[1]**2)**0.5
def rotate(self, angle):"""rotate self counterclockwise by angle
"""
perp =Vec2D(-self[1], self[0])
angle = angle * math.pi /180.0
c, s = math.cos(angle), math.sin(angle)returnVec2D(self[0]*c+perp[0]*s, self[1]*c+perp[1]*s)
def __getnewargs__(self):return(self[0], self[1])
def __repr__(self):return"(%.2f,%.2f)"% self
Vec2Dを見ると、実際にはタプルであることがわかります。TNavigatorクラスを見ると次のようになります。
classTNavigator(object):"""Navigation part of the RawTurtle.
Implements methodsfor turtle movement."""
START_ORIENTATION ={"standard":Vec2D(1.0,0.0),"world":Vec2D(1.0,0.0),"logo":Vec2D(0.0,1.0)}
DEFAULT_MODE ="standard"
DEFAULT_ANGLEOFFSET =0
DEFAULT_ANGLEORIENT =1
次に、 TNavigator.START_ORIENTATION [self._mode]
を確認し、 _mode
が TNavigator
クラスの standard
であることを確認します。このとき、 TNavigator.START_ORIENTATION [self._mode]
は Vec2D(1.0、0.0)
です。
次に、_gotoメソッドを見てください。
def _goto(self, end):"""Move the pen to the point end, thereby drawing a line
if pen is down. All other methods for turtle movement depend
on this one."""
## Version with undo-stuff
go_modes =( self._drawing,
self._pencolor,
self._pensize,isinstance(self._fillpath, list))
screen = self.screen
undo_entry =("go", self._position, end, go_modes,(self.currentLineItem,
self.currentLine[:],
screen._pointlist(self.currentLineItem),
self.items[:]))if self.undobuffer:
self.undobuffer.push(undo_entry)
start = self._position
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))
delta = diff *(1.0/nhops)for n inrange(1, nhops):if n ==1:
top = True
else:
top = False
self._position = start + delta * n
if self._drawing:
screen._drawline(self.drawingLineItem,(start, self._position),
self._pencolor, self._pensize, top)
self._update()if self._drawing:
screen._drawline(self.drawingLineItem,((0,0),(0,0)),
fill="", width=self._pensize)
# Turtle now at end,if self._drawing: # now update currentLine
self.currentLine.append(end)ifisinstance(self._fillpath, list):
self._fillpath.append(end)
###### vererbung!!!!!!!!!!!!!!!!!!!!!!
self._position = end
if self._creatingPoly:
self._poly.append(end)iflen(self.currentLine)>42: # 42! answer to the ultimate question
# of life, the universe and everything
self._newLine()
self._update() #count=True)
goto_メソッドでは、最初のコメントは、メソッドの機能を説明しています。「現在の位置から入力終了パラメーター座標点に移動し、移動する過程で、線セグメントを描画します。すべてのタートル描画メソッドはこれに基づいています。 goto_method」。 goto_メソッドでは、最初にタプルgo_modesが定義されています。
go_modes =( self._drawing,
self._pencolor,
self._pensize,isinstance(self._fillpath, list))
go_modesタプルでは、_drawing、_pencolor、および_pensizeが渡され、isinstanceメソッドが呼び出されて、_fillpathがリストであるかどうかが判別されます。その後、undo_entryタプルが作成されます。 if self.undobuffer:
を判断した後、それが空またはNullの場合、 self.undobuffer.push(undo_entry)
。次に、デフォルト状態の描画メソッド:
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))
delta = diff *(1.0/nhops)for n inrange(1, nhops):if n ==1:
top = True
else:
top = False
self._position = start + delta * n
if self._drawing:
screen._drawline(self.drawingLineItem,(start, self._position),
self._pencolor, self._pensize, top)
self._update()if self._drawing:
screen._drawline(self.drawingLineItem,((0,0),(0,0)),
fill="", width=self._pensize)
その中で、開始は現在位置の座標点であり、終了は目標位置の座標点です。上記の主な方法の中で最も重要なのは、 _drawline
、構成パラメーター、座標シーケンス、ペンの色、および描画線を渡すために _drawline
を使用することです。幅と polyitem
を指定するかどうか;(特定の座標シーケンスのアルゴリズムを理解していません。計算と式が何であるかを知っている学生が教えてくれることを願っています、ありがとう!)。
_drawlineの実装を表示します。
def _drawline(self, lineitem, coordlist=None,
fill=None, width=None, top=False):"""Configure lineitem according to provided arguments:
coordlist is sequence of coordinates
fill is drawing color
width is width of drawn line.
top is a boolean value, which specifies if polyitem
will be put on top of the canvas' displaylist so it
will not be covered by other items."""
if coordlist is not None:
cl =[]for x, y in coordlist:
cl.append(x * self.xscale)
cl.append(-y * self.yscale)
self.cv.coords(lineitem,*cl)if fill is not None:
self.cv.itemconfigure(lineitem, fill=fill)if width is not None:
self.cv.itemconfigure(lineitem, width=width)if top:
self.cv.tag_raise(lineitem)
**上記の記事は完全に分析および実装されておらず、後で更新されます。 ****
Recommended Posts