Amit Jaiswal - 1 year ago 194
Python Question

# How to draw smily (arc) using python turtle

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?

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.

Source (Stackoverflow)