通过两点和半径可以确定一个或者两个圆心,具体的公式推导可以看看这位大佬的文章,已经讲的很详细了。
通过两点坐标,半径和弧线的顺时针逆时针方向得到圆心坐标,并且输出该圆弧中间的坐标点和近似切线角度。
在这里默认输入的两个点和半径是可以组成一个圆的。并且需要注意的是:不考虑特殊情况(如两点中间的距离等于直径,两点x值相等等),由于可以得到两个圆心,因此即使知道是顺时针或者逆时针方向,根据圆心的不同也能够得到两条圆弧(小圆弧和大圆弧)
我这里单纯取一个圆心输出弧线上的点坐标和切线角度。
import math
def get_circle_center(x1, y1, x2, y2, r):
# 计算两点之间的距离
d = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
#print(d)
if x1 == x2 and y1 == y2:
print("no result")
elif d / 2 == r:
center_x = (x1 + x2) / 2
center_y = (y1 + y2) / 2
print("d == r")
elif x1 == x2:
center_y = (y1 + y2) / 2
center_x = x1 + math.sqrt(r * r - ((y1 - y2) / 2) * ((y1 - y2) / 2))
else:
c1 = (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) / (2 * (x2 - x1))
c2 = (y2 - y1) / (x2 - x1)
A = c2 * c2 + 1
B = 2 * x1 * c1 - c1 * c1 - 2 * y1
C = x1 * x1 - 2 * x1 * c1 + c1 * c1 + y1 * y1 + r * r
print(B * B - 4 * A * C)
center_y = (-B + math.sqrt(B * B - 4 * A * C)) / (2 * A) #还有另外一个值:(-B - math.sqrt(B * B - 4 * A * C)) / (2 * A)
center_x = c1 - c2 * center_y
return center_x, center_y
def get_point(center_x, center_y, x1, y1, x2, y2, r, clockwise):
start_angle = math.atan2(y1 - center_y, x1 - center_x)
end_angle = math.atan2(y2 - center_y, x2 - center_x)
#判断顺时针和逆时针
if clockwise:
if start_angle < end_angle:
start_angle += 2 * math.pi
else:
if end_angle < start_angle:
end_angle += 2 * math.pi
# 计算角度差
angle_diff = end_angle - start_angle
'''
if angle_diff < 0:
angle_diff += 2 * math.pi
print("angle_diff < 0")
'''
num_points = 100
point_list = []
for i in range(num_points + 1):
angle = start_angle + i * angle_diff / num_points
x = center_x + r * math.cos(angle)
y = center_y + r * math.sin(angle)
grad = math.atan2((center_y + r * math.sin(start_angle + (i + 1) * angle_diff / num_points)) - y, (center_x + r * math.cos(start_angle + (i + 1) * angle_diff / num_points)) - x)
point_list.append((x, y, grad))
size = len(point_list)
return point_list, size
print (get_circle_center(0, 0, 0, 2, 1))
x0, y0 = get_circle_center(0, 0, 0, 2, 1)
clockwise = True #true为顺时针,false为逆时针
print(get_point(x0, y0, 0, 0, 0, 2, 1, clockwise))