Amit Jaiswal - 1 year ago 205

Python Question

I want to draw a smily using python turtle. Circle extent will be 120.

I am trying following

`import turtle`

turtle.circle(100)

turtle.up()

turtle.goto(0, 30)

turtle.down()

turtle.circle(40, 120)

Problem is smile part. How to draw a face smile?

Answer Source

The `turtle`

module does not provide advanced methods to drow arcs of circles or parabolas, however it isn't hard to come up with the right equations.

A circle `C`

with origin at `(x0, y0)`

and radius `r`

is described by the equation:

```
(x-x0)^2 + (y-y0)^2 = r^2
```

We can expand this to get:

```
x^2 -2x·x0 + x0^2 + y^2 -2y·y0 + y0^2 - r^2 = 0
```

Now we can take for example the `y`

as variable and obtain the second degree equation:

```
y^2 -2y0·y +(x^2-2x0·x+x0^2+y0^2-r^2) = 0
```

Let `d = x^2-2x0·x+x0^2+y0^2-r^2`

. We can solve this using the usual formula:

```
y1 = (2y0 + sqrt(4y0^2 - 4d))/2 = y0 + sqrt(y0^2 - d)
y2 = (2y0 - sqrt(4y0^2 - 4d))/2 = y0 - sqrt(y0^2 - d)
```

So now you can write down a function that, given the coordinates of the center of the circle and the radius, and the value for `x`

it returns the coordinate `y`

and use these coordinates to move the turtle:

```
def find_circle_coord(x0, y0, r, x):
d = x**2 - 2*x0*x + x0**2 + y0**2 - r**2
D = y0**2 - d
if D < 0:
raise ValueError("Value for x is outside the circle!")
return y0 - D**.5, y0 + D**.5
```

As in:

```
>>> # bob is a turtle
>>> bob.pendown()
>>> for x in range(-50, 50):
... y1, _ = find_circle_coord(0, 0, 100, x)
... bob.goto(x, y1)
```

By choosing one of the two coordinates returned you choose whether to draw the "upper" or "lower" arc.

to draw a smile you simply have to come up with two circles one smaller and a larger one but with the center slightly above the previous one so that they have that kind of intersection.

So you have to choose a circle `C1`

centered in `x0, y0`

with radius `r`

and a circle `C2`

centered in `x0, y0+K`

with radius `R > r`

.
Note that C2's center is vertically aligned with C1 center (hence the same `x`

coordinate for the center) but it is above it (note: I'm not sure of `y`

-axis orientation so the `+K`

might be `-K`

...)

To find the intersections you have to solve the system of their equations:

```
(x-x0)^2 + (y-y0)^2-r^2 = 0
(x-x0^2) + (y-y0-K)^2-R^2 = 0
```

Now subtracting the second equation from the first you get:

```
(y-y0)^2 - (y-y0-K)^2 -r^2 + R^2 = 0
y^2 -2y·y0 +y0^2 - y^2 -y0^2 -K^2 +2y·y0 +2K·y -2K·y0 -r^2 + R^2 = 0
-K^2 +2K·y -2K·y0 -r^2 + R^2 = 0
```

Where you get:

```
y = (K^2 +2K·y0 +r^2 -R^2)/(2K)
```

And you can substitute the `y`

in one of the circle equations to obtain the `x`

s corresponding to such `y`

. Then you know which `x`

to draw using `find_circle_coord`

.

If you want to make the mouth more open you could use a circle and a parabola. To find the `y`

value of a point on a parabole it's easy:

```
def find_parabola_coord(a, b, c, x):
return a*x**2 + b*x + c
```

Or you could use the form of equation of a parabola given its vertex `V = (xv, yv)`

:

```
y - yv = a(x - xv)^2
```

where `a`

controls how steep the parabola is.