Advertisement
Guest User

Untitled

a guest
Dec 14th, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.92 KB | None | 0 0
  1. import sys
  2. import math
  3.  
  4. def get_plane(x1, y1, z1, x2, y2, z2, x3, y3, z3):
  5. normale = [(y2-y1)*(z3-z1) - (z2-z1)*(y3-y1), (z2-z1)*(x3-x1) - (x2-x1)*(z3-z1), (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1)]
  6. A = normale[0]
  7. B = normale[1]
  8. C = normale[2]
  9. D = -x1*normale[0] - y1*normale[1] - z1*normale[2]
  10. return A, B, C, D
  11.  
  12. def fourth_triangle_vertex(x1, y1, z1, x2, y2, z2, x3, y3, z3):
  13. h_x = (x1 + x3) / 2.0
  14. h_y = (y1 + y3) / 2.0
  15. h_z = (z1 + z3) / 2.0
  16. e_x = x2 + (h_x - x2) * 2.0
  17. e_y = y2 + (h_y - y2) * 2.0
  18. e_z = z2 + (h_z - z2) * 2.0
  19. return e_x, e_y, e_z
  20.  
  21. def count_delta(matrix):
  22. return matrix[0][0] * (matrix[1][1]*matrix[2][2] - matrix[1][2]*matrix[2][1]) - matrix[0][1] * (matrix[1][0]*matrix[2][2] - matrix[1][2]*matrix[2][0]) + matrix[0][2] * (matrix[1][0]*matrix[2][1] - matrix[1][1]*matrix[2][0])
  23.  
  24. def crummer(matrix, free):
  25. delta = count_delta(matrix)
  26. if delta == 0.0:
  27. raise ValueError
  28. nm = [[matrix[0][0], matrix[0][1], matrix[0][2]], [matrix[1][0], matrix[1][1], matrix[1][2]], [matrix[2][0], matrix[2][1], matrix[2][2]]]
  29. nm[0][0] = free[0]
  30. nm[1][0] = free[1]
  31. nm[2][0] = free[2]
  32. delta1 = count_delta(nm)
  33. nm = [[matrix[0][0], matrix[0][1], matrix[0][2]], [matrix[1][0], matrix[1][1], matrix[1][2]], [matrix[2][0], matrix[2][1], matrix[2][2]]]
  34. nm[0][1] = free[0]
  35. nm[1][1] = free[1]
  36. nm[2][1] = free[2]
  37. delta2 = count_delta(nm)
  38. nm = [[matrix[0][0], matrix[0][1], matrix[0][2]], [matrix[1][0], matrix[1][1], matrix[1][2]], [matrix[2][0], matrix[2][1], matrix[2][2]]]
  39. nm[0][2] = free[0]
  40. nm[1][2] = free[1]
  41. nm[2][2] = free[2]
  42. delta3 = count_delta(nm)
  43. return delta1 / delta, delta2 / delta, delta3 / delta
  44.  
  45. class Mirror:
  46. def __init__(self, x1, y1, z1, x2, y2, z2, x3, y3, z3):
  47. self.x1 = x1
  48. self.x2 = x2
  49. self.x3 = x3
  50. self.y1 = y1
  51. self.y2 = y2
  52. self.y3 = y3
  53. self.z1 = z1
  54. self.z2 = z2
  55. self.z3 = z3
  56.  
  57.  
  58. class Brink:
  59. def __init__(self, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4):
  60. self.x1 = x1
  61. self.x2 = x2
  62. self.x3 = x3
  63. self.y1 = y1
  64. self.y2 = y2
  65. self.y3 = y3
  66. self.z1 = z1
  67. self.z2 = z2
  68. self.z3 = z3
  69. self.x4 = x4
  70. self.y4 = y4
  71. self.z4 = z4
  72.  
  73. class Ray:
  74. def normalize_vector(self):
  75. while max(abs(self.dir_x), abs(self.dir_y), abs(self.dir_z)) < 1.0:
  76. self.dir_x *= 2.0
  77. self.dir_y *= 2.0
  78. self.dir_z *= 2.0
  79. otrX = self.dir_x < 0.0
  80. otrY = self.dir_y < 0.0
  81. otrZ = self.dir_z < 0.0
  82. self.dir_x = abs(self.dir_x)
  83. self.dir_y = abs(self.dir_y)
  84. self.dir_z = abs(self.dir_z)
  85. coef = max(self.dir_x, self.dir_y, self.dir_z)
  86. self.dir_x /= coef
  87. self.dir_y /= coef
  88. self.dir_z /= coef
  89. if otrX:
  90. self.dir_x *= -1.0
  91. if otrY:
  92. self.dir_y *= -1.0
  93. if otrZ:
  94. self.dir_z *= -1.0
  95.  
  96. def __init__(self, x, y, z, dir_x, dir_y, dir_z, e):
  97. self.x = x
  98. self.y = y
  99. self.z = z
  100. self.dir_x = dir_x
  101. self.dir_y = dir_y
  102. self.dir_z = dir_z
  103. self.energy = e
  104.  
  105. def cross_plane(self, A, B, C, D):
  106. x1 = self.x
  107. y1 = self.y
  108. z1 = self.z
  109. m1 = self.dir_x
  110. p1 = self.dir_y
  111. l1 = self.dir_z
  112. if p1 != 0.0:
  113. matrix = [[p1, -m1, 0.0], [0.0, l1, -p1], [A, B, C]]
  114. free = [p1*x1 - m1*y1, l1*y1 - p1*z1, -D]
  115. try:
  116. r1, r2, r3 = map(float, crummer(matrix, free))
  117. return r1, r2, r3
  118. except ValueError:
  119. raise ValueError
  120. elif m1 != 0.0:
  121. matrix = [[p1, -m1, 0.0], [l1, 0.0, -m1], [A, B, C]]
  122. free = [p1*x1 - m1*y1, l1*x1 - m1*z1, -D]
  123. try:
  124. r1, r2, r3 = map(float, crummer(matrix, free))
  125. return r1, r2, r3
  126. except ValueError:
  127. raise ValueError
  128. else:
  129. matrix = [[0.0, l1, -p1], [l1, 0.0, -m1], [A, B, C]]
  130. free = [l1*y1 - p1*z1, l1*x1 - m1*z1, -D]
  131. try:
  132. r1, r2, r3 = map(float, crummer(matrix, free))
  133. return r1, r2, r3
  134. except ValueError:
  135. raise ValueError
  136.  
  137. def reflect_mirror(self, mirror, op = False):
  138. A, B, C, D = map(float, get_plane(mirror.x1, mirror.y1, mirror.z1, mirror.x2, mirror.y2, mirror.z2, mirror.x3, mirror.y3, mirror.z3))
  139. try:
  140. p_x, p_y, p_z = map(float, self.cross_plane(A, B, C, D))
  141. except ValueError:
  142. raise ValueError
  143.  
  144.  
  145. if self.dir_x != 0.0:
  146. k = (p_x - self.x) / self.dir_x
  147. elif self.dir_y != 0.0:
  148. k = (p_y - self.y) / self.dir_y
  149. else:
  150. k = (p_z - self.z) / self.dir_z
  151. if k <= 0.0:
  152. raise ValueError
  153.  
  154. mir_x = p_x + self.dir_x
  155. mir_y = p_y + self.dir_y
  156. mir_z = p_z + self.dir_z
  157.  
  158. ort_ray = Ray(mir_x, mir_y, mir_z, A, B, C, 0)
  159. ort_x, ort_y, ort_z = map(float, ort_ray.cross_plane(A, B, C, D))
  160.  
  161. mir_x = mir_x + (ort_x - mir_x) * 2
  162. mir_y = mir_y + (ort_y - mir_y) * 2
  163. mir_z = mir_z + (ort_z - mir_z) * 2
  164.  
  165. return k, p_x, p_y, p_z, mir_x - p_x, mir_y - p_y, mir_z - p_z
  166.  
  167.  
  168. sys.stdin = open("input.txt", "r")
  169. sys.stdout = open("output.txt", "w")
  170.  
  171. x_a, y_a, z_a = map(float, input().split())
  172. x_b, y_b, z_b = map(float, input().split())
  173. x_c, y_c, z_c = map(float, input().split())
  174. x_d, y_d, z_d = map(float, input().split())
  175.  
  176. brinks = []
  177. x_e, y_e, z_e = map(float, fourth_triangle_vertex(x_a, y_a, z_a, x_b, y_b, z_b, x_c, y_c, z_c))
  178. brinks.append(Brink(x_a, y_a, z_a, x_b, y_b, z_b, x_c, y_c, z_c, x_e, y_e, z_e))
  179. x_f, y_f, z_f = map(float, fourth_triangle_vertex(x_e, y_e, z_e, x_c, y_c, z_c, x_d, y_d, z_d))
  180. brinks.append(Brink(x_e, y_e, z_e, x_c, y_c, z_c, x_d, y_d, z_d, x_f, y_f, z_f))
  181. x_g, y_g, z_g = map(float, fourth_triangle_vertex(x_b, y_b, z_b, x_c, y_c, z_c, x_d, y_d, z_d))
  182. brinks.append(Brink(x_b, y_b, z_b, x_c, y_c, z_c, x_d, y_d, z_d, x_g, y_g, z_g))
  183. x_h, y_h, z_h = map(float, fourth_triangle_vertex(x_f, y_f, z_f, x_d, y_d, z_d, x_g, y_g, z_g))
  184. brinks.append(Brink(x_f, y_f, z_f, x_d, y_d, z_d, x_g, y_g, z_g, x_h, y_h, z_h))
  185.  
  186. brinks.append(Brink(x_a, y_a, z_a, x_e, y_e, z_e, x_f, y_f, z_f, x_h, y_h, z_h))
  187. brinks.append(Brink(x_a, y_a, z_a, x_b, y_b, z_b, x_g, y_g, z_g, x_h, y_h, z_h))
  188.  
  189. dir_x, dir_y, dir_z = map(float, input().split())
  190. ent_x, ent_y, ent_z = map(float, input().split())
  191. e = int(input())
  192. cur_ray = Ray(ent_x, ent_y, ent_z, dir_x, dir_y, dir_z, e)
  193.  
  194. mirrors = []
  195.  
  196. n = int(input())
  197. for i in range(n):
  198. x_p, y_p, z_p = map(float, input().split())
  199. x_q, y_q, z_q = map(float, input().split())
  200. x_r, y_r, z_r = map(float, input().split())
  201. mirrors.append(Mirror(x_p, y_p, z_p, x_q, y_q, z_q, x_r, y_r, z_r))
  202.  
  203. lastRefl = -1
  204.  
  205. min_x = 10000000.0
  206. max_x = -10000000.0
  207. min_y = 10000000.0
  208. max_y = -10000000.0
  209. min_z = 10000000.0
  210. max_z = -10000000.0
  211.  
  212. for i in range(len(brinks)):
  213. min_x = min(min_x, min(brinks[i].x1, brinks[i].x2, brinks[i].x3, brinks[i].x4))
  214. max_x = max(max_x, max(brinks[i].x1, brinks[i].x2, brinks[i].x3, brinks[i].x4))
  215. min_y = min(min_y, min(brinks[i].y1, brinks[i].y2, brinks[i].y3, brinks[i].y4))
  216. max_y = max(max_y, max(brinks[i].y1, brinks[i].y2, brinks[i].y3, brinks[i].y4))
  217. min_z = min(min_z, min(brinks[i].z1, brinks[i].z2, brinks[i].z3, brinks[i].z4))
  218. max_z = max(max_z, max(brinks[i].z1, brinks[i].z2, brinks[i].z3, brinks[i].z4))
  219.  
  220. reflected = 0
  221.  
  222. while 1:
  223. cur_ray.normalize_vector()
  224. reflects = False
  225. vec_len = 10000000.0
  226. idx = 0
  227.  
  228. for i in range(len(mirrors)):
  229. if lastRefl == i:
  230. continue
  231. try:
  232. vl, p_x, p_y, p_z, dir_x, dir_y, dir_z = map(float, cur_ray.reflect_mirror(mirrors[i]))
  233. reflects = True
  234. if vl < vec_len:
  235. vec_len = vl
  236. idx = i
  237. except ValueError:
  238. continue
  239.  
  240.  
  241. if reflects:
  242. vl, p_x, p_y, p_z, dir_x, dir_y, dir_z = map(float, cur_ray.reflect_mirror(mirrors[idx], False))
  243. p_x = round(p_x, 8)
  244. p_y = round(p_y, 8)
  245. p_z = round(p_z, 8)
  246. if (p_x >= min_x and p_x <= max_x and p_y >= min_y and p_y <= max_y and p_z >= min_z and p_z <= max_z):
  247. reflected += 1
  248. cur_ray.energy -= 1
  249. cur_ray.x = p_x
  250. cur_ray.y = p_y
  251. cur_ray.z = p_z
  252. cur_ray.dir_x = dir_x
  253. cur_ray.dir_y = dir_y
  254. cur_ray.dir_z = dir_z
  255. cur_ray.x = round(cur_ray.x, 8)
  256. cur_ray.y = round(cur_ray.y, 8)
  257. cur_ray.z = round(cur_ray.z, 8)
  258. cur_ray.dir_x = round(cur_ray.dir_x, 8)
  259. cur_ray.dir_y = round(cur_ray.dir_y, 8)
  260. cur_ray.dir_z = round(cur_ray.dir_z, 8)
  261. lastRefl = idx
  262. if cur_ray.energy == 0:
  263. print(0)
  264. print(cur_ray.x, cur_ray.y, cur_ray.z)
  265. exit(0)
  266. continue
  267.  
  268. for i in range(len(brinks)):
  269. A, B, C, D = map(float, get_plane(brinks[i].x1, brinks[i].y1, brinks[i].z1, brinks[i].x2, brinks[i].y2, brinks[i].z2, brinks[i].x3, brinks[i].y3, brinks[i].z3))
  270. try:
  271. p_x, p_y, p_z = map(float, cur_ray.cross_plane(A, B, C, D))
  272. if cur_ray.dir_x != 0.0:
  273. k = (p_x - cur_ray.x) / cur_ray.dir_x
  274. elif cur_ray.dir_y != 0.0:
  275. k = (p_y - cur_ray.y) / cur_ray.dir_y
  276. else:
  277. k = (p_z - cur_ray.z) / cur_ray.dir_z
  278. if k < 0.0:
  279. continue
  280. if k == 0.0 and reflected == 0:
  281. continue
  282. p_x = round(p_x, 8)
  283. p_y = round(p_y, 8)
  284. p_z = round(p_z, 8)
  285. if not(p_x >= min_x and p_x <= max_x and p_y >= min_y and p_y <= max_y and p_z >= min_z and p_z <= max_z):
  286. continue
  287. print(1)
  288. print(cur_ray.energy)
  289. print(p_x, p_y, p_z)
  290. print(cur_ray.dir_x, cur_ray.dir_y, cur_ray.dir_z)
  291. break
  292. except:
  293. continue
  294. exit(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement