根据相互距离指定n个点的二维坐标。
方案
1. 首先指定前3个点的坐标(根据2个圆)
- 设置常量Ax, Ay作为A点坐标
- A与B的距离为Dab,则B点坐标设置为Bx = Ax - Dab, By = Ay
- C与A的距离为Dac作为第1个圆的半径R1,C与B的距离为Dbc作为第2个圆的半径R2
- 以A点为圆心,R1为半径画圆1,以B点为圆心,R2为半径画圆2
- 两个交点任选一个作为C点坐标
2. 然后指定剩余n-3个点的坐标(根据3个圆)
- 利用A、B和C三个点依次确定剩余点的坐标
- 对于剩余点中的某一个点P
- P与A的距离为Dap作为第1个圆的半径R1,P与B的距离为Dbp作为第2个圆的半径R2
- 以A点为圆心,R1为半径画圆1,以B点为圆心,R2为半径画圆2
- 得到两个交点,根据P与C的距离确定P点坐标
- 完成
实现
1 | # 已知n个点两两之间的距离,指定他们的坐标,相互距离保持不变 |
2 | import math |
3 | import numpy as np |
4 | |
5 | |
6 | # 用欧式距离计算样本集的距离矩阵 |
7 | # 参数:样本集x,类型为np.array |
8 | def get_distance(x): |
9 | size = len(x) |
10 | distance = np.zeros(shape=(len(x), len(x))) |
11 | for i in range(0, size - 1): |
12 | for j in range(i + 1, size): |
13 | distance[i][j] = np.sqrt(np.sum(np.power(x[i] - x[j], 2))) |
14 | distance[j][i] = distance[i][j] |
15 | return distance |
16 | |
17 | |
18 | # 计算2个圆的交点 |
19 | def circle_2(p1, r1, p2, r2): |
20 | x = p1[0] |
21 | y = p1[1] |
22 | R = r1 |
23 | a = p2[0] |
24 | b = p2[1] |
25 | S = r2 |
26 | d = math.sqrt((abs(a - x)) ** 2 + (abs(b - y)) ** 2) |
27 | if d > (R + S) or d < (abs(R - S)): |
28 | print("Two circles have no intersection!") |
29 | return |
30 | elif d == 0 and R == S: |
31 | print("Two circles have same center!") |
32 | return |
33 | else: |
34 | A = (R ** 2 - S ** 2 + d ** 2) / (2 * d) |
35 | h = math.sqrt(R ** 2 - A ** 2) |
36 | x2 = x + A * (a - x) / d |
37 | y2 = y + A * (b - y) / d |
38 | x3 = round(x2 - h * (b - y) / d, 2) |
39 | y3 = round(y2 + h * (a - x) / d, 2) |
40 | x4 = round(x2 + h * (b - y) / d, 2) |
41 | y4 = round(y2 - h * (a - x) / d, 2) |
42 | c1 = np.array([x3, y3]) # 第1个交点 |
43 | c2 = np.array([x4, y4]) # 第2个交点 |
44 | return c1, c2 |
45 | |
46 | |
47 | # 计算3个圆的交点 |
48 | def circle_3(p1, r1, p2, r2, p3, r3): |
49 | c1, c2 = circle_2(p1, r1, p2, r2) # 前2个交点 |
50 | # 从c1和c2中选择正确的一个 |
51 | d1 = np.sqrt(np.power(c1[0] - p3[0], 2) + np.power(c1[1] - p3[1], 2)) |
52 | d2 = np.sqrt(np.power(c2[0] - p3[0], 2) + np.power(c2[1] - p3[1], 2)) |
53 | if d1 == r3: |
54 | return c1 |
55 | elif d2 == r3: |
56 | return c2 |
57 | |
58 | |
59 | # 指定坐标 |
60 | def set_coordinate(dist): |
61 | # 先固定前三个点 |
62 | x = [5] # 第1个点的x坐标 |
63 | y = [5] # 第1个点的y坐标 |
64 | x.append(5-dist[0][1]) # 第2个点的x坐标 |
65 | y.append(5) # 第2个点的y坐标 |
66 | a = np.array([x[0], y[0]]) # a点坐标 |
67 | b = np.array([x[1], y[1]]) # b点坐标 |
68 | r1 = dist[0][2] # a、c点距离 |
69 | r2 = dist[1][2] # b、c点距离 |
70 | C = circle_2(a, r1, b, r2) # c点坐标 |
71 | c = C[0] |
72 | x.append(c[0]) |
73 | y.append(c[1]) |
74 | # 现在前三个点a,b,c坐标已知,现在指定剩余的n-3个点 |
75 | for i in range(3, len(dist)): |
76 | Ra = dist[0][i] |
77 | Rb = dist[1][i] |
78 | Rc = dist[2][i] |
79 | c = np.array(c) |
80 | P = circle_3(a, Ra, b, Rb, c, Rc) |
81 | new_x = P[0] |
82 | new_y = P[1] |
83 | x.append(new_x) |
84 | y.append(new_y) |
85 | return x, y |
86 | |
87 | |
88 | if __name__ == '__main__': |
89 | x = [[1, 1], [2, 1], [2, 2], [3, 3], [4, 2], [4, 6], [2, 7]] |
90 | dist = get_distance(np.array(x)) |
91 | X, Y = set_coordinate(dist) |
92 | xx = [] |
93 | for i in range(0, len(X)): |
94 | xx.append([X[i], Y[i]]) |
95 | print(xx) # 指定后n个点的二维坐标列表,形式同x |