trilateration3d.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. from __future__ import division
  2. import json
  3. import math
  4. from json import encoder
  5. import itertools
  6. encoder.FLOAT_REPR = lambda o: format(o, '.2f')
  7. class base_station(object):
  8. def __init__(self, lat, lon, dist):
  9. self.lat = lat
  10. self.lon = lon
  11. self.dist = dist
  12. class point(object):
  13. def __init__(self, x, y, z):
  14. self.x = x
  15. self.y = y
  16. self.z = z
  17. class circle(object):
  18. def __init__(self, point, radius):
  19. self.center = point
  20. self.radius = radius
  21. class json_data(object):
  22. def __init__(self, circles, inner_points, center):
  23. self.circles = circles
  24. self.inner_points = inner_points
  25. self.center = center
  26. def serialize_instance(obj):
  27. d = {}
  28. d.update(vars(obj))
  29. return d
  30. def get_two_points_distance(p1, p2):
  31. distance = math.sqrt(pow((p1.x - p2.x), 2) + pow((p1.y - p2.y), 2) + pow((p1.z - p2.z), 2))
  32. return distance
  33. def get_two_circles_intersecting_points(c1, c2, c3):
  34. p1 = c1.center
  35. p2 = c2.center
  36. p3 = c3.center
  37. r1 = c1.radius
  38. r2 = c2.radius
  39. r3 = c3.radius
  40. if r1 > 1000 or r2 > 1000 or r3 > 1000:
  41. return None
  42. else:
  43. v1 = (p2.x - p1.x, p2.y - p1.y, p2.z - p1.z)
  44. v2 = (p3.x - p1.x, p3.y - p1.y, p3.z - p1.z)
  45. cross_product = (v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2],
  46. v1[0] * v2[1] - v1[1] * v2[0])
  47. if cross_product == (0, 0, 0):
  48. return None
  49. else:
  50. d12 = get_two_points_distance(p1, p2)
  51. d13 = get_two_points_distance(p1, p3)
  52. d23 = get_two_points_distance(p2, p3)
  53. if (r1 + r2) > d12 > math.fabs(r1 - r2) \
  54. and (r1 + r3) > d13 > math.fabs(r1 - r3) \
  55. and (r2 + r3) > d23 > math.fabs(r2 - r3):
  56. X21 = p2.x - p1.x
  57. X31 = p3.x - p1.x
  58. Y21 = p2.y - p1.y
  59. Y31 = p3.y - p1.y
  60. Z21 = p2.z - p1.z
  61. Z31 = p3.z - p1.z
  62. A1 = pow(r1, 2) - pow(p1.x, 2) - pow(p1.y, 2) - pow(p1.z, 2)
  63. A2 = pow(r2, 2) - pow(p2.x, 2) - pow(p2.y, 2) - pow(p2.z, 2)
  64. A3 = pow(r3, 2) - pow(p3.x, 2) - pow(p3.y, 2) - pow(p3.z, 2)
  65. A21 = -(A2 - A1) / 2
  66. A31 = -(A3 - A1) / 2
  67. D = X21 * Y31 - Y21 * X31
  68. B0 = (A21 * Y31 - A31 * Y21) / D
  69. B1 = (Y21 * Z31 - Y31 * Z21) / D
  70. C0 = (A31 * X21 - A21 * X31) / D
  71. C1 = (X31 * Z21 - X21 * Z31) / D
  72. E = (pow(B1, 2) + pow(C1, 2) + 1)
  73. F = (B1 * (B0 - p1.x) + C1 * (C0 - p1.y) - p1.z)
  74. G = pow((B0 - p1.x), 2) + pow((C0 - p1.y), 2) + pow(p1.z, 2) - pow(r1, 2)
  75. if 4 * pow(F, 2) - 4 * E * G < 0:
  76. return None
  77. else:
  78. z1 = (-F + math.sqrt(pow(F, 2) - E * G)) / E
  79. x1 = B0 + B1 * z1
  80. y1 = C0 + C1 * z1
  81. z2 = (-F - math.sqrt(pow(F, 2) - E * G)) / E
  82. x2 = B0 + B1 * z2
  83. y2 = C0 + C1 * z2
  84. return[point(x1, y1, z1), point(x2, y2, z2)]
  85. else:
  86. return None
  87. def get_all_intersecting_points(circles):
  88. points = []
  89. num = len(circles)
  90. for i, j, k in itertools.combinations(range(num), 3):
  91. res = get_two_circles_intersecting_points(circles[i], circles[j], circles[k])
  92. if res:
  93. points.extend(res)
  94. return points
  95. def is_contained_in_circles(point, circles):
  96. for i in range(len(circles)):
  97. # if (get_two_points_distance(point, circles[i].center) > (circles[i].radius)):
  98. if abs(get_two_points_distance(point, circles[i].center) - circles[i].radius) > 0.2:
  99. return False
  100. return True
  101. def get_polygon_center(points):
  102. center = point(0, 0, 0)
  103. if len(points) == 0:
  104. return None
  105. else:
  106. num = len(points)
  107. for i in range(num):
  108. center.x += points[i].x
  109. center.y += points[i].y
  110. center.z += points[i].z
  111. center.x /= num
  112. center.y /= num
  113. center.z /= num
  114. return center
  115. def trilateration3d(MapBSList, dataMap):
  116. circle_list = []
  117. for key, value in dataMap.items():
  118. center = point(MapBSList[key][0], MapBSList[key][1], MapBSList[key][2])
  119. bscircle = circle(center, value)
  120. circle_list.append(bscircle)
  121. inner_points = []
  122. for p in get_all_intersecting_points(circle_list):
  123. if is_contained_in_circles(p, circle_list):
  124. inner_points.append(p)
  125. if len(inner_points) > 0:
  126. center = get_polygon_center(inner_points)
  127. else:
  128. center = None
  129. return center
  130. if __name__ == '__main__':
  131. p1 = point(8.43, 14.35, 11.5)
  132. p2 = point(5.59, -4.65, 1.5)
  133. p3 = point(7.526, 11.74, 1.5)
  134. p4 = point(0, 0, 1.5)
  135. c1 = circle(p1, 4.51)
  136. c2 = circle(p2, 17.25)
  137. c3 = circle(p3, 20.98)
  138. c4 = circle(p4, 19.64)
  139. circle_list = [c1, c2, c3, c4]
  140. inner_points = []
  141. a = get_all_intersecting_points(circle_list)
  142. for p in get_all_intersecting_points(circle_list):
  143. if is_contained_in_circles(p, circle_list):
  144. inner_points.append(p)
  145. center = get_polygon_center(inner_points)
  146. in_json = json_data([c1, c2, c3, c4], [p1, p2, p3, p4], center)
  147. out_json = json.dumps(in_json, sort_keys=True,
  148. indent=4, default=serialize_instance)
  149. print(out_json)