三角関数を使わずに円を描く

# 突然ですが、この関数で円が描けます。

三角関数を一切使わずに、円を描くロジック _（Adafruitの[GFX-Library](https://github.com/adafruit/Adafruit-GFX-Library/blob/master/Adafruit_GFX.cpp)を参考にした）_。

```python
def circle(center, radius, color):
    x0, y0 = center
    f = 1 - radius
    ddF_x = 1
    ddF_y = -2 * radius
    x = 0
    y = radius
    pixel((x0, y0 + radius), color)
    pixel((x0, y0 - radius), color)
    pixel((x0 + radius, y0), color)
    pixel((x0 - radius, y0), color)
    while x < y:
        if f >= 0:
            y -= 1
            ddF_y += 2
            f += ddF_y
        x += 1
        ddF_x += 2
        f += ddF_x
        pixel((x0 + x, y0 + y), color)
        pixel((x0 - x, y0 + y), color)
        pixel((x0 + x, y0 - y), color)
        pixel((x0 - x, y0 - y), color)
        pixel((x0 + y, y0 + x), color)
        pixel((x0 - y, y0 + x), color)
        pixel((x0 + y, y0 - x), color)
        pixel((x0 - y, y0 - x), color) 
```

- center：中心座標 (x, y)
- radius：半径
- color：色



`pixel(position, color)`：座標 (x, y) に点を描画する関数

# 実際に描いてみた

pygameを使い、実際に描いてみた。
- 外側の黒い円：circle関数[`pygame.draw.circle`](https://www.pygame.org/docs/ref/draw.html#pygame.draw.circle)で描いた円
- 内側の<font color=red>赤い円</font>：冒頭のコードで描いた円。


![circle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/fa66d686-5eb4-5f7e-a97e-096227f55e71.png)


遜色なし。すご

<br><br>

_アルゴリズムの差でしょうか、同じ半径にしてもピッタリとは重ならない。_

<img width="300" alt="circle2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/01602ca1-bf30-a673-a65c-5ffd2c24512c.png" />




<!-- 
<details><summary>コード</summary>

```python
import sys
import pygame
from pygame.locals import *

Radius = 240
Diameter = Radius * 2
Center = (Radius, Radius)

Green = Color(0, 255, 0)
Red = Color(255, 0, 0)
Black = Color(0, 0, 0)
White = Color(255, 255, 255)

pygame.init()
Surface = pygame.display.set_mode((Diameter, Diameter))
pygame.display.set_caption(f"Exsample {Diameter}x{Diameter}")

def pixel(position, color):
    pygame.draw.line(Surface, color, position, position, width=1)

def circle(center, radius, color):
    x0, y0 = center
    f = 1 - radius
    ddF_x = 1
    ddF_y = -2 * radius
    x = 0
    y = radius
    pixel((x0, y0 + radius), color)
    pixel((x0, y0 - radius), color)
    pixel((x0 + radius, y0), color)
    pixel((x0 - radius, y0), color)
    while x < y:
        if f >= 0:
            y -= 1
            ddF_y += 2
            f += ddF_y
        x += 1
        ddF_x += 2
        f += ddF_x
        pixel((x0 + x, y0 + y), color)
        pixel((x0 - x, y0 + y), color)
        pixel((x0 + x, y0 - y), color)
        pixel((x0 - x, y0 - y), color)
        pixel((x0 + y, y0 + x), color)
        pixel((x0 - y, y0 + x), color)
        pixel((x0 + y, y0 - x), color)
        pixel((x0 - y, y0 - x), color)

def main():
    while True:
        Surface.fill(White)

        pygame.draw.circle(Surface, Black, Center, Radius - 10, width=1)
        circle(Center, Radius - 18, Red)

        pygame.display.update()

        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        pygame.time.delay(1 * 1000) # delay 1s

main()
```
</details>
-->

# おわりに

自分には、どういう定理に基づいたアルゴリズムか分かりませんが、想像以上に綺麗に描けるので、ここに残しておきます。

元々は[SSD1306ライブラリ](https://github.com/stlehmann/micropython-ssd1306)に円の描画関数がなかったことがきっかけ。

以上