Reputation: 65610
I have 2 points on a circle and the angle between them and I would like to find the center of the circle that is thus defined (well, both centers preferably).
def find_center(p1,p2,angle):
# magic happens... What to do here?
return (center_x, center_y)
Upvotes: -2
Views: 5251
Reputation: 1
@Dhara's answer needs to divide the angle by two as @Panos pointed out. Unfortunately, I couldn't post a comment due to my low reputation. Here is the code (also adapted to use matplotlib and numpy). There are two possible centers, the other one can be obtained by providing the negative value of the angle as an argument.
import matplotlib.pyplot as plt
import numpy as np
def find_center(p1, p2, angle):
angle = angle/2
# End points of the chord
x1, y1 = p1
x2, y2 = p2
# Slope of the line through the chord
slope = (y1-y2)/(x1-x2)
# Slope of a line perpendicular to the chord
new_slope = -1/slope
# Point on the line perpendicular to the chord
# Note that this line also passes through the center of the circle
xm, ym = (x1+x2)/2, (y1+y2)/2
# Distance between p1 and p2
d_chord = ((x1-x2)**2 + (y1-y2)**2)**0.5
# Distance between xm, ym and center of the circle (xc, yc)
d_perp = d_chord/(2*np.tan(angle))
# Equation of line perpendicular to the chord: y-ym = new_slope(x-xm)
# Distance between xm,ym and xc, yc: (yc-ym)^2 + (xc-xm)^2 = d_perp^2
# Substituting from 1st to 2nd equation for y,
# we get: (new_slope^2+1)(xc-xm)^2 = d^2
# Solve for xc:
xc = (d_perp)/(new_slope**2+1)**0.5 + xm
# Solve for yc:
yc = (new_slope)*(xc-xm) + ym
return xc, yc
def find_two_centers(p1, p2, angle):
return find_center(p1, p2, angle), find_center(p1, p2, -angle)
plt.figure()
p1 = [1., 2.]
p2 = [-3, 4.]
angle = np.pi/2
xc, yc = find_center(p1, p2, angle)
# Calculate the radius and draw a circle
r = ((xc-p1[0])**2 + (yc-p1[1])**2)**0.5
cir = plt.Circle((xc,yc), radius=r, fc='y')
plt.gca().add_patch(cir)
# mark p1 and p2 and the center of the circle
plt.plot(p1[0], p1[1], 'ro')
plt.plot(p2[0], p2[1], 'ro')
plt.plot(xc, yc, 'go')
plt.axis('equal')
xc, yc = find_center(p1, p2, -angle)
# Calculate the radius and draw a circle
r = ((xc-p1[0])**2 + (yc-p1[1])**2)**0.5
cir = plt.Circle((xc,yc), radius=r, fc='y')
plt.gca().add_patch(cir)
# mark p1 and p2 and the center of the circle
plt.plot(p1[0], p1[1], 'ro')
plt.plot(p2[0], p2[1], 'ro')
plt.plot(xc, yc, 'go')
plt.axis('equal')
plt.show()
Upvotes: 0
Reputation: 1
Only it seems like it should be: d_perp = d_chord/(2*tan(angle/2))
.
# Distance between xm, ym and center of the circle (xc, yc)
d_perp = d_chord/(2*tan(angle))
Upvotes: 0
Reputation: 6767
Here is my solution with the test code
from pylab import *
from numpy import *
def find_center(p1, p2, angle):
# End points of the chord
x1, y1 = p1
x2, y2 = p2
# Slope of the line through the chord
slope = (y1-y2)/(x1-x2)
# Slope of a line perpendicular to the chord
new_slope = -1/slope
# Point on the line perpendicular to the chord
# Note that this line also passes through the center of the circle
xm, ym = (x1+x2)/2, (y1+y2)/2
# Distance between p1 and p2
d_chord = sqrt((x1-x2)**2 + (y1-y2)**2)
# Distance between xm, ym and center of the circle (xc, yc)
d_perp = d_chord/(2*tan(angle))
# Equation of line perpendicular to the chord: y-ym = new_slope(x-xm)
# Distance between xm,ym and xc, yc: (yc-ym)^2 + (xc-xm)^2 = d_perp^2
# Substituting from 1st to 2nd equation for y,
# we get: (new_slope^2+1)(xc-xm)^2 = d^2
# Solve for xc:
xc = (d_perp)/sqrt(new_slope**2+1) + xm
# Solve for yc:
yc = (new_slope)*(xc-xm) + ym
return xc, yc
if __name__=='__main__':
p1 = [1., 2.]
p2 = [-3, 4.]
angle = pi/6
xc, yc = find_center(p1, p2,angle)
# Calculate the radius and draw a circle
r = sqrt((xc-p1[0])**2 + (yc-p1[1])**2)
cir = Circle((xc,yc), radius=r, fc='y')
gca().add_patch(cir)
# mark p1 and p2 and the center of the circle
plot(p1[0], p1[1], 'ro')
plot(p2[0], p2[1], 'ro')
plot(xc, yc, 'go')
show()
Upvotes: 6
Reputation: 21
# Solve for xc:
xc = (d_perp)/sqrt(new_slope**2+1) +xm # looks like +xm got omitted!)
# Solve for yc:
yc = (new_slope)*(xc-xm)+ym
you also need to check for x1=x2
# Slope of the line through the chord
if x1==x2
slope = 999999
else
slope = (y1-y2)/(x1-x2)
Upvotes: 2
Reputation: 617
you have to solve the triangle p1 p2 c. You have one angle. The other two angles are (180-angle)/2 Calculate side p1 p2 (distance) Then calculate the side p1 c this gives you the radius r of the circle. The solutions are the two points that are the intersection of the circles with center p1 and center p2 and radius r.
Upvotes: 1
Reputation: 21249
I'm really rusty on this stuff, so this might be a bit off, but it should get you started. Also, I don't know python, so this is just the pseudocode:
//check to ensure...
//The two points aren't the same
//The angle isn't zero
//Other edge cases
//Get the distance between the points
x_dist = x2 - x1;
y_dist = y2 - y1;
//Find the length of the 'opposite' side of the right triangle
dist_opp = (sqrt((x_dist)^2 + (y_dist)^2)));
x_midpoint = (x1 - (x_dist / 2);
y_midpoint = (y1 - (y_dist / 2);
theta = the_angle / 2; //the right triangle's angle is half the starting angle
dist_adj = cotangent(theta) * dist_opp;//find the right triangle's length
epsilon = sqrt((-y_dist)^2 + x_dist^2);
segments = epsilon / dist_adj;
x_center = x_midpoint + (x_dist * segments);
y_center = y_midpoint + (y_dist * segments);
Upvotes: 1