iam_agf
iam_agf

Reputation: 689

Give 3 points and a plot circle

I want to give the points [0,1],[1,0] and [0,-1] to python and plot the circle that passes over them. Does exists a python module that make this? I have tried using matplotlib:

import matplotlib.pyplot as plt
plt.plot([0,1,0],[1,0,-1])
plt.show()

But only gave me two lines.

Upvotes: 9

Views: 21234

Answers (5)

DieterDP
DieterDP

Reputation: 4347

This code also lets you easily check whether the 3 points form a line or not.

def define_circle(p1, p2, p3):
    """
    Returns the center and radius of the circle passing the given 3 points.
    In case the 3 points form a line, returns (None, infinity).
    """
    temp = p2[0] * p2[0] + p2[1] * p2[1]
    bc = (p1[0] * p1[0] + p1[1] * p1[1] - temp) / 2
    cd = (temp - p3[0] * p3[0] - p3[1] * p3[1]) / 2
    det = (p1[0] - p2[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p2[1])
    
    if abs(det) < 1.0e-6:
        return (None, np.inf)
    
    # Center of circle
    cx = (bc*(p2[1] - p3[1]) - cd*(p1[1] - p2[1])) / det
    cy = ((p1[0] - p2[0]) * cd - (p2[0] - p3[0]) * bc) / det
    
    radius = np.sqrt((cx - p1[0])**2 + (cy - p1[1])**2)
    return ((cx, cy), radius)

And to solve the original question:

center, radius = define_circle((0,1), (1,0), (0,-1))
if center is not None:
    plt.figure(figsize=(4, 4))
    circle = plt.Circle(center, radius)
    plt.gcf().gca().add_artist(circle)

(Adjusted from here)

Upvotes: 19

lucidbrot
lucidbrot

Reputation: 6156

I was very curious why the accepted answer by Alex Martelli works. And I had to create a report for my lecture anyway, so I'm pasting it here for posterity.

enter image description here enter image description here

Upvotes: 5

Rutherford
Rutherford

Reputation: 21

Given three points whose coordinates are:

(p,t) (q,u) (s,z)

...the equation of the circle defined by those three points is:

x^2 + y^2 + Ax + By + C = 0

where:

A=((u-t)*z^2+(-u^2+t^2-q^2+p^2)*z+t*u^2+(-t^2+s^2-p^2)*u+(q^2-s^2)*t)/((q-p)*z+(p-s)*u+(s-q)*t)

B=-((q-p)*z^2+(p-s)*u^2+(s-q)*t^2+(q-p)*s^2+(p^2-q^2)*s+p*q^2-p^2*q)/((q-p)*z+(p-s)*u+(s-q)*t)

C=-((p*u-q*t)*z^2+(-p*u^2+q*t^2-p*q^2+p^2*q)*z+s*t*u^2+(-s*t^2+p*s^2-p^2*s)*u+(q^2*s-q*s^2)*t)/((q-p)*z+(p-s)*u+(s-q)*t)

The above is the general solution. You can put the formulas for A, B, and C into your program and find the equation for any circle, given 3 points.

For your particular problem with points (0,1) (1,0) (0,-1) you will get:

A=0

B=0

C=-1

... so the equation will be

x^2 + y^2 -1 = 0 (the unit circle)

Upvotes: 2

Alex Martelli
Alex Martelli

Reputation: 881537

There was a "code golf" question exactly matching this (except that the circle's equation was requested, rather than plotting it) -- see https://codegolf.stackexchange.com/questions/2289/circle-through-three-points . Unraveling the first and shortest (Python) solution into more readable, less-hacky form to match your exact specs - but keeping the core idea of using complex numbers for simpler calculations:

x, y, z = 0+1j, 1+0j, 0-1j
w = z-x
w /= y-x
c = (x-y)*(w-abs(w)**2)/2j/w.imag-x
print '(x%+.3f)^2+(y%+.3f)^2 = %.3f^2' % (c.real, c.imag, abs(c+x))

OK, this still "prints the equation" rather than "plotting the circle", but, we're getting close:-). To actually plot the circle in matplotlib, see e.g plot a circle with pyplot -- in the solution above, c is the (negated) center of the circle (as a complex number, so use .real and .imag for the x/y coordinates), and abs(c+x) the radius (a real number, abs makes it so).

Upvotes: 18

ljetibo
ljetibo

Reputation: 3094

To draw a circle in matplotlib, first you need to declare an artist

circle = plt.Circle((0,0), 2)

you then have to add that artist to an instance of axes:

fig, ax = plt.subplots()
ax.add_artist(circle)

then you can draw it safely.

plt.show()

Notice that artist Circle takes (x,y) coordinates of the circle's center, and radius r. That means you're going to have to calculate those values yourself.

Upvotes: 1

Related Questions