Pythonタートルライブラリ実装の基本的な分析

タートルの関連する使用法については、["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

Pythonタートルライブラリ実装の基本的な分析
python標準ライブラリのglobの分析
Pythonの基本構文
Pythonの基礎知識(1)
Python操作の一般的なメソッドの分析Jiraライブラリ
AI自動マットサンプル分析のPython実装
wavファイルのPython分析
PythonクローラーのJSの分析
gomokuプログラムのPython実装
Pythonサンドボックスエスケープの分析
Pythonオブジェクト指向プログラミングの分析
Pythonイールドの使用例の分析
Pythonプラグインメカニズムの詳細な実装
pythonリストの逆トラバーサルの実装
IOU計算ケースのPython実装
word2vec操作のPython予備実装
FMアルゴリズム分析とPython実装
Pythonファイル操作の基本的なプロセス分析
pythonselenium操作cookieの実装
Python条件付き制御ステートメントの分析
python3登録グローバルホットキーの実装
python学生管理システムの実装
Pythonモジュールの知識の完全な分析
python勾配降下アルゴリズムの実装
pythonでのJWTユーザー認証の実装
交差点のPython実装とIOUチュートリアル
Pythonガベージコレクションメカニズムの詳細な分析
Pythonクラスの動的バインディングの実装原則
Python言語の本質:Itertoolsライブラリ
Pythonマルチプロセスプログラミングの一般的な方法の分析
pythonインポートライブラリの特定の方法
C言語プログラムを呼び出すPythonのメソッド分析
Pythonの基本構文(1)
Python3の基本構文
Python3.9の7つの機能
python標準ライブラリOSモジュールの詳細な説明
Pythonの基本的な要約
Pythonデータ分析
ファイルをダウンロードするためのPythonヘッドレスクローラーの実装
手描き効果の例の共有のPython実装
pythonによる名刺管理システムの実装
Pythonの基本的な演算子
Pythonは釣りマスターのゲーム実装を書きます
pythonに基づく名刺管理システムの実装
Pythonインターフェース開発の実装手順の詳細な説明
Pythonの基本的な構文ジェネレータ
Pythonの基本的な描画チュートリアル(1)
Python関数の基礎学習
Python線形補間分析
Python構文の基本
python_クローラーの基本的な学習
Pythonの基本的なデータタイプ
pythonのPrettytableモジュール
Pythonの基本的なデータタイプ
09.Python3の共通モジュール
Pythonの基本的な構文の反復