Coverage for src/km3pipe/tests/test_math.py: 100%

346 statements  

« prev     ^ index     » next       coverage.py v7.5.1, created at 2024-05-08 03:14 +0000

1# Filename: test_math.py 

2# pylint: disable=locally-disabled,C0111,R0904,C0103 

3 

4import numpy as np 

5from numpy.testing import assert_almost_equal, assert_allclose 

6import pytest 

7 

8from km3pipe.testing import TestCase 

9from km3pipe import Table 

10from km3pipe.math import ( 

11 angle, 

12 angle_between, 

13 magnitude, 

14 dist, 

15 pld3, 

16 com, 

17 zenith, 

18 azimuth, 

19 Polygon, 

20 IrregularPrism, 

21 rotation_matrix, 

22 spherecutmask, 

23 spherecut, 

24 SparseCone, 

25 space_angle, 

26 hsin, 

27 phi, 

28 theta, 

29 unit_vector, 

30 log_b, 

31 qeuler, 

32 qrot, 

33 qrot_yaw, 

34 intersect_3d, 

35) 

36 

37__author__ = ["Tamas Gal", "Moritz Lotze"] 

38__copyright__ = "Copyright 2016, KM3Pipe devs and the KM3NeT collaboration." 

39__credits__ = ["Thomas Heid"] 

40__license__ = "MIT" 

41__maintainer__ = ["Tamas Gal", "Moritz Lotze"] 

42__email__ = "tgal@km3net.de" 

43__status__ = "Development" 

44 

45 

46class TestMath(TestCase): 

47 def setUp(self): 

48 # self.vecs = np.array([[0., 1., 5.], 

49 # [1., 1., 4.], 

50 # [2., 1., 3.], 

51 # [3., 1., 2.], 

52 # [4., 1., 1.]]) 

53 # self.v = (1, 2, 3) 

54 self.v = np.array([0.26726124, 0.53452248, 0.80178373]) 

55 self.vecs = np.array( 

56 [ 

57 [0.0, 0.19611614, 0.98058068], 

58 [0.23570226, 0.23570226, 0.94280904], 

59 [0.53452248, 0.26726124, 0.80178373], 

60 [0.80178373, 0.26726124, 0.53452248], 

61 [0.94280904, 0.23570226, 0.23570226], 

62 ] 

63 ) 

64 

65 def test_phi(self): 

66 print(phi((1, 0, 0))) 

67 assert_almost_equal(0, phi((1, 0, 0))) 

68 assert_almost_equal(np.pi, phi((-1, 0, 0))) 

69 assert_almost_equal(np.pi / 2, phi((0, 1, 0))) 

70 assert_almost_equal(np.pi / 2 * 3, phi((0, -1, 0))) 

71 assert_almost_equal(np.pi / 2 * 3, phi((0, -1, 0))) 

72 assert_almost_equal(0, phi((0, 0, 0))) 

73 assert_almost_equal(phi(self.v), 1.10714872) 

74 assert_almost_equal( 

75 phi(self.vecs), 

76 np.array([1.57079633, 0.78539816, 0.46364761, 0.32175055, 0.24497866]), 

77 ) 

78 

79 def test_zenith(self): 

80 assert_allclose(np.pi, zenith((0, 0, 1))) 

81 assert_allclose(0, zenith((0, 0, -1))) 

82 assert_allclose(np.pi / 2, zenith((0, 1, 0))) 

83 assert_allclose(np.pi / 2, zenith((0, -1, 0))) 

84 assert_allclose(np.pi / 4 * 3, zenith((0, 1, 1))) 

85 assert_allclose(np.pi / 4 * 3, zenith((0, -1, 1))) 

86 assert_almost_equal(zenith(self.v), 2.5010703409103687) 

87 assert_allclose( 

88 zenith(self.vecs), 

89 np.array([2.94419709, 2.80175574, 2.50107034, 2.13473897, 1.80873745]), 

90 ) 

91 

92 def test_azimuth(self): 

93 self.assertTrue(np.allclose(np.pi, azimuth((1, 0, 0)))) 

94 self.assertTrue(np.allclose(0, azimuth((-1, 0, 0)))) 

95 

96 print(azimuth((0, 1, 0))) 

97 print(azimuth((0, -1, 0))) 

98 print(azimuth((0, 0, 0))) 

99 print(azimuth(self.v)) 

100 print(azimuth(self.vecs)) 

101 self.assertTrue(np.allclose(np.pi / 2 * 3, azimuth((0, 1, 0)))) 

102 self.assertTrue(np.allclose(np.pi / 2, azimuth((0, -1, 0)))) 

103 self.assertTrue(np.allclose(np.pi, azimuth((0, 0, 0)))) 

104 self.assertTrue(np.allclose(azimuth(self.v), 4.24874137138)) 

105 self.assertTrue( 

106 np.allclose( 

107 azimuth(self.vecs), 

108 np.array([4.71238898, 3.92699082, 3.60524026, 3.46334321, 3.38657132]), 

109 ) 

110 ) 

111 

112 def test_theta(self): 

113 print(theta((0, 0, -1))) 

114 print(theta((0, 0, 1))) 

115 print(theta((0, 1, 0))) 

116 print(theta((0, -1, 0))) 

117 print(theta((0, 1, 1))) 

118 print(theta((0, -1, 1))) 

119 print(theta(self.v)) 

120 print(theta(self.vecs)) 

121 self.assertTrue(np.allclose(0, theta((0, 0, 1)))) 

122 self.assertTrue(np.allclose(np.pi, theta((0, 0, -1)))) 

123 self.assertTrue(np.allclose(np.pi / 2, theta((0, 1, 0)))) 

124 self.assertTrue(np.allclose(np.pi / 2, theta((0, -1, 0)))) 

125 self.assertTrue(np.allclose(0, theta((0, 1, 1)))) 

126 self.assertTrue(np.allclose(0, theta((0, -1, 1)))) 

127 self.assertTrue(np.allclose(theta(self.v), 0.64052231)) 

128 self.assertTrue( 

129 np.allclose( 

130 theta(self.vecs), 

131 np.array([0.19739554, 0.33983691, 0.64052231, 1.00685369, 1.3328552]), 

132 ) 

133 ) 

134 

135 def test_unit_vector(self): 

136 v1 = (1, 0, 0) 

137 v2 = (1, 1, 0) 

138 v3 = (-1, 2, 0) 

139 assert np.allclose(v1, unit_vector(v1)) 

140 assert np.allclose(np.array(v2) / np.sqrt(2), unit_vector(v2)) 

141 assert np.allclose(np.array(v3) / np.sqrt(5), unit_vector(v3)) 

142 

143 def test_magnitude(self): 

144 assert 1 == magnitude(np.array([1, 0, 0])) 

145 assert 2 == magnitude(np.array([0, 2, 0])) 

146 assert 3 == magnitude(np.array([0, 0, 3])) 

147 assert np.allclose( 

148 [3.74165739, 8.77496439, 13.92838828], 

149 magnitude(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])), 

150 ) 

151 

152 def test_angle(self): 

153 v1 = np.array([1, 0, 0]) 

154 v2 = np.array([0, 1, 0]) 

155 v3 = np.array([-1, 0, 0]) 

156 self.assertAlmostEqual(0, angle(v1, v1)) 

157 self.assertAlmostEqual(np.pi / 2, angle(v1, v2)) 

158 self.assertAlmostEqual(np.pi, angle(v1, v3)) 

159 self.assertAlmostEqual(angle(self.v, v1), 1.3002465638163236) 

160 self.assertAlmostEqual(angle(self.v, v2), 1.0068536854342678) 

161 self.assertAlmostEqual(angle(self.v, v3), 1.8413460897734695) 

162 

163 assert np.allclose( 

164 [1.300246563816323, 1.0068536854342678, 1.8413460897734695], 

165 angle(np.array([self.v, self.v, self.v]), np.array([v1, v2, v3])), 

166 ) 

167 

168 def test_angle_between(self): 

169 v1 = (1, 0, 0) 

170 v2 = (0, 1, 0) 

171 v3 = (-1, 0, 0) 

172 self.assertAlmostEqual(0, angle_between(v1, v1)) 

173 self.assertAlmostEqual(np.pi / 2, angle_between(v1, v2)) 

174 self.assertAlmostEqual(np.pi, angle_between(v1, v3)) 

175 self.assertAlmostEqual(angle_between(self.v, v1), 1.3002465638163236) 

176 self.assertAlmostEqual(angle_between(self.v, v2), 1.0068536854342678) 

177 self.assertAlmostEqual(angle_between(self.v, v3), 1.8413460897734695) 

178 

179 assert np.allclose( 

180 [0.0, 0.0, 0.0] 

181 - angle_between(np.array([v1, v2, v3]), np.array([v1, v2, v3]), axis=1), 

182 0, 

183 ) 

184 assert np.allclose( 

185 [np.pi / 2, np.pi] 

186 - angle_between(np.array([v1, v1]), np.array([v2, v3]), axis=1), 

187 0, 

188 ) 

189 

190 self.assertTrue( 

191 np.allclose( 

192 angle_between(self.vecs, v1), 

193 np.array([1.57079633, 1.3328552, 1.0068537, 0.64052231, 0.33983691]), 

194 ) 

195 ) 

196 self.assertTrue( 

197 np.allclose( 

198 angle_between(self.vecs, v2), 

199 np.array([1.37340077, 1.3328552, 1.3002466, 1.30024656, 1.3328552]), 

200 ) 

201 ) 

202 self.assertTrue( 

203 np.allclose( 

204 angle_between(self.vecs, v3), 

205 np.array([1.57079633, 1.80873745, 2.13473897, 2.50107034, 2.80175574]), 

206 ) 

207 ) 

208 

209 def test_angle_between_returns_nan_for_zero_length_vectors(self): 

210 v1 = (0, 0, 0) 

211 v2 = (1, 0, 0) 

212 with pytest.warns(RuntimeWarning): 

213 self.assertTrue(np.isnan(angle_between(v1, v2))) 

214 

215 def test_space_angle(self): 

216 p1 = (np.pi / 2, np.pi) 

217 p2 = (np.pi, 0) 

218 self.assertAlmostEqual( 

219 space_angle(p1[0], p2[0], p1[1], p2[1]), 1.57079632679489 

220 ) 

221 p3 = (0, np.pi) 

222 p4 = (np.pi / 2, 0) 

223 self.assertAlmostEqual( 

224 space_angle(p3[0], p4[0], p3[1], p4[1]), 1.57079632679489 

225 ) 

226 

227 def test_hsin(self): 

228 assert np.all(hsin((np.pi, 0)) == (1, 0)) 

229 self.assertAlmostEqual(hsin(np.pi / 2), 0.5) 

230 

231 def test_pld3(self): 

232 p1 = np.array((0, 0, 0)) 

233 p2 = np.array((0, 0, 1)) 

234 d2 = np.array((0, 1, 0)) 

235 self.assertAlmostEqual(1, pld3(p1, p2, d2)) 

236 p1 = np.array((0, 0, 0)) 

237 p2 = np.array((0, 0, 2)) 

238 d2 = np.array((0, 1, 0)) 

239 self.assertAlmostEqual(2, pld3(p1, p2, d2)) 

240 p1 = np.array((0, 0, 0)) 

241 p2 = np.array((0, 0, 0)) 

242 d2 = np.array((0, 1, 0)) 

243 self.assertAlmostEqual(0, pld3(p1, p2, d2)) 

244 p1 = np.array((1, 2, 3)) 

245 p2 = np.array((4, 5, 6)) 

246 d2 = np.array((7, 8, 9)) 

247 self.assertAlmostEqual(0.5275893, pld3(p1, p2, d2)) 

248 p1 = np.array((0, 0, 2)) 

249 p2 = np.array((-100, 0, -100)) 

250 d2 = np.array((1, 0, 1)) 

251 self.assertAlmostEqual(1.4142136, pld3(p1, p2, d2)) 

252 p1 = np.array([183.0, -311.0, 351.96083871]) 

253 p2 = np.array([40.256, -639.888, 921.93]) 

254 d2 = np.array([0.185998, 0.476123, -0.859483]) 

255 self.assertAlmostEqual(21.25456308, pld3(p1, p2, d2)) 

256 

257 def test_com(self): 

258 center_of_mass = com(((1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12))) 

259 self.assertEqual((5.5, 6.5, 7.5), tuple(center_of_mass)) 

260 center_of_mass = com(((1, 2, 3), (4, 5, 6), (7, 8, 9)), masses=(1, 0, 0)) 

261 self.assertEqual((1, 2, 3), tuple(center_of_mass)) 

262 center_of_mass = com(((1, 1, 1), (0, 0, 0))) 

263 self.assertEqual((0.5, 0.5, 0.5), tuple(center_of_mass)) 

264 

265 

266class TestShapes(TestCase): 

267 def setUp(self): 

268 self.poly = [ 

269 (-60, 120), 

270 (80, 120), 

271 (110, 60), 

272 (110, -30), 

273 (70, -110), 

274 (-70, -110), 

275 (-90, -70), 

276 (-90, 60), 

277 ] 

278 

279 def test_poly_containment(self): 

280 polygon = Polygon(self.poly) 

281 point_in = (-40, -40) 

282 point_out = (-140, -140) 

283 points = [ 

284 (-40, -40), 

285 (-140, -140), 

286 (40, -140), 

287 ] 

288 assert np.all(polygon.contains(point_in)) 

289 assert not np.any(polygon.contains(point_out)) 

290 assert np.all(polygon.contains(points) == [True, False, False]) 

291 

292 def test_poly_xy(self): 

293 polygon = Polygon(self.poly) 

294 x = (-40, -140, 40) 

295 y = (-40, -140, -140) 

296 assert np.all(polygon.contains_xy(x, y) == [True, False, False]) 

297 

298 def test_prism_contained(self): 

299 z = (-90, 90) 

300 prism = IrregularPrism(self.poly, z[0], z[1]) 

301 points = [ 

302 (0, 1, 2), 

303 (-100, 20, 10), 

304 (10, 90, 10), 

305 ] 

306 assert np.all(prism.contains(points) == [True, False, True]) 

307 

308 def test_prism_contained_xyz(self): 

309 z = (-90, 90) 

310 prism = IrregularPrism(self.poly, z[0], z[1]) 

311 x = (0, -100, 10) 

312 y = (1, 20, 90) 

313 z = (2, 10, 10) 

314 assert np.all(prism.contains_xyz(x, y, z) == [True, False, True]) 

315 

316 

317class TestRotation(TestCase): 

318 def test_rotmat(self): 

319 v = [3, 5, 0] 

320 axis = [4, 4, 1] 

321 theta = 1.2 

322 newvec = np.dot(rotation_matrix(axis, theta), v) 

323 self.assertTrue( 

324 np.allclose(newvec, np.array([2.74911638, 4.77180932, 1.91629719])) 

325 ) 

326 

327 def test_cone(self): 

328 spike = [1, 1, 0] 

329 bottom = [0, 2, 0] 

330 angle = np.pi / 4 

331 n_angles = 20 

332 cone = SparseCone(spike, bottom, angle) 

333 circ_samp = cone.sample_circle(n_angles=n_angles) 

334 axis_samp = cone.sample_axis 

335 samp = cone.sample(n_angles) 

336 assert len(circ_samp) == n_angles 

337 assert len(axis_samp) == 2 

338 assert len(samp) == len(circ_samp) + 2 

339 

340 

341class TestSphereCut(TestCase): 

342 def test_spherecut_mask(self): 

343 center = (0.0, 0.0, 0.0) 

344 items = Table( 

345 { 

346 "pos_x": [0, 10, 0, 20, 0], 

347 "pos_y": [10, 0, 0, 0, 30], 

348 "pos_z": [0, 0, 10, 0, 0], 

349 } 

350 ) 

351 rmin = 0.0 

352 rmax = 10.0 

353 self.assertListEqual( 

354 list(spherecutmask(center, rmin, rmax, items)), 

355 [True, True, True, False, False], 

356 ) 

357 

358 def test_with_table(self): 

359 center = (0.0, 0.0, 0.0) 

360 items = Table( 

361 { 

362 "pos_x": [0, 10, 0, 20, 0], 

363 "pos_y": [10, 0, 0, 0, 30], 

364 "pos_z": [0, 0, 10, 0, 0], 

365 } 

366 ) 

367 rmin = 0.0 

368 rmax = 10.0 

369 selected_items = spherecut(center, rmin, rmax, items) 

370 assert len(selected_items) == 3 

371 self.assertListEqual( 

372 list(items[spherecutmask(center, rmin, rmax, items)]), list(selected_items) 

373 ) 

374 

375 def test_with_array(self): 

376 center = (0.0, 0.0, 0.0) 

377 items = np.array([[0, 10, 0], [10, 0, 0], [0, 0, 10], [20, 0, 0], [0, 30, 0]]) 

378 rmin = 0.0 

379 rmax = 10.0 

380 selected_items = [list(e) for e in spherecut(center, rmin, rmax, items)] 

381 assert len(selected_items) == 3 

382 assert [0, 10, 0] in selected_items 

383 assert [10, 0, 0] in selected_items 

384 assert [0, 0, 10] in selected_items 

385 

386 def test_center(self): 

387 center = (0.0, 10.0, 0.0) 

388 items = Table( 

389 { 

390 "pos_x": [0, 10, 0, 20, 0], 

391 "pos_y": [10, 0, 0, 0, 30], 

392 "pos_z": [0, 0, 10, 0, 0], 

393 } 

394 ) 

395 rmin = 0.0 

396 rmax = 15.0 

397 selected_items = spherecut(center, rmin, rmax, items) 

398 assert len(selected_items) == 3 

399 self.assertListEqual( 

400 list(items[spherecutmask(center, rmin, rmax, items)]), list(selected_items) 

401 ) 

402 

403 def test_rmin(self): 

404 center = (0.0, 0.0, 0.0) 

405 items = np.array([[0, 10, 0], [10, 0, 0], [0, 0, 10], [20, 0, 0], [0, 30, 0]]) 

406 rmin = 20.0 

407 rmax = 40.0 

408 selected_items = [list(e) for e in spherecut(center, rmin, rmax, items)] 

409 assert len(selected_items) == 2 

410 assert [20, 0, 0] in selected_items 

411 assert [0, 30, 0] in selected_items 

412 

413 

414class TestLog(TestCase): 

415 def test_val(self): 

416 assert_allclose(log_b(5, 2), np.log2(5)) 

417 assert_allclose(log_b(5, 10), np.log10(5)) 

418 assert_allclose(log_b(5, np.e), np.log(5)) 

419 

420 

421class TestQeuler(TestCase): 

422 def test_conversion_of_yaw(self): 

423 assert np.allclose([1, 0, 0, 0], qeuler(0, 0, 0)) 

424 assert np.allclose([0.7071, 0, 0, 0.7071], qeuler(90, 0, 0)) 

425 assert np.allclose([0, 0, 0, 1], qeuler(180, 0, 0)) 

426 assert np.allclose([-0.7071, 0, 0, 0.7071], qeuler(270, 0, 0)) 

427 assert np.allclose([-1, 0, 0, 0], qeuler(360, 0, 0)) 

428 

429 def test_conversion_of_pitch(self): 

430 assert np.allclose([0.92388, 0, 0.38268, 0], qeuler(0, 45, 0)) 

431 assert np.allclose([0.92388, 0, -0.38268, 0], qeuler(0, -45, 0)) 

432 assert np.allclose([0.7071, 0, 0.7071, 0], qeuler(0, 90, 0)) 

433 assert np.allclose([0.8660254, 0, 0.5, 0], qeuler(0, 60, 0)) 

434 assert np.allclose([-0.96592583, 0, -0.25881905, 0], qeuler(0, 390, 0)) 

435 

436 def test_conversion_of_roll(self): 

437 assert np.allclose([0.92388, 0.38268, 0, 0], qeuler(0, 0, 45)) 

438 assert np.allclose([0.92388, -0.38268, 0, 0], qeuler(0, 0, -45)) 

439 assert np.allclose([0.70710, 0.70710, 0, 0], qeuler(0, 0, 90)) 

440 assert np.allclose([0.86602, 0.5, 0, 0], qeuler(0, 0, 60)) 

441 assert np.allclose([-0.96592583, -0.25881905, 0, 0], qeuler(0, 0, 390)) 

442 

443 def test_mixed_conversion(self): 

444 assert np.allclose( 

445 [0.999471, 0.02601972, 0.01767416, 0.00826538], qeuler(1, 2, 3) 

446 ) 

447 assert np.allclose( 

448 [0.94371436, 0.26853582, -0.14487813, 0.12767944], qeuler(10, -20, 30) 

449 ) 

450 assert np.allclose( 

451 [-0.16575384, -0.69624819, 0.05479592, -0.69624819], qeuler(-999, 999, -999) 

452 ) 

453 

454 

455class TestQrot(TestCase): 

456 def test_rotation_of_x_vector(self): 

457 assert np.allclose([0, 1, 0], qrot([1, 0, 0], qeuler(90, 0, 0))) 

458 assert np.allclose([-1, 0, 0], qrot([1, 0, 0], qeuler(180, 0, 0))) 

459 assert np.allclose([-1, 0, 0], qrot([1, 0, 0], qeuler(180, 0, -45))) 

460 assert np.allclose([0, 0, -1], qrot([1, 0, 0], qeuler(180, 90, 45))) 

461 

462 def test_rotation_of_y_vector(self): 

463 assert np.allclose([-1, 0, 0], qrot([0, 1, 0], qeuler(90, 0, 0))) 

464 assert np.allclose([0, -1, 0], qrot([0, 1, 0], qeuler(180, 0, 0))) 

465 assert np.allclose( 

466 [0, -0.70710, -0.70710], qrot([0, 1, 0], qeuler(180, 0, -45)) 

467 ) 

468 assert np.allclose( 

469 [-0.70710, -0.70710, 0], qrot([0, 1, 0], qeuler(180, 90, 45)) 

470 ) 

471 

472 def test_rotation_of_z_vector(self): 

473 assert np.allclose([0, 0, 1], qrot([0, 0, 1], qeuler(90, 0, 0))) 

474 assert np.allclose([0, 0, 1], qrot([0, 0, 1], qeuler(180, 0, 0))) 

475 assert np.allclose([0, -0.70710, 0.70710], qrot([0, 0, 1], qeuler(180, 0, -45))) 

476 assert np.allclose([-0.70710, 0.70710, 0], qrot([0, 0, 1], qeuler(180, 90, 45))) 

477 

478 def test_mixed_rotation(self): 

479 assert np.allclose([1, 2, 3], qrot([1, 2, 3], qeuler(0, 0, 0))) 

480 assert np.allclose([0, -1.414213, 0], qrot([0, 1, -1], qeuler(180, 90, 45))) 

481 assert np.allclose([-1.41421356, 0, -1], qrot([1, 1, 1], qeuler(180, 90, 45))) 

482 assert np.allclose( 

483 [-14.1421356, 0, -10], qrot([10, 10, 10], qeuler(180, 90, 45)) 

484 ) 

485 

486 

487class TestQrotYaw(TestCase): 

488 def test_call_with_list(self): 

489 qrot_yaw([1, 2, 3], 1) 

490 

491 def test_no_rotation(self): 

492 vec = (1, 0, 0) 

493 vec_rot = qrot_yaw(vec, 0) 

494 assert np.allclose([1, 0, 0], vec_rot) 

495 

496 def test_a_rotation_of_90(self): 

497 vec = (1, 0, 0) 

498 vec_rot = qrot_yaw(vec, 90) 

499 assert np.allclose([0, 1, 0], vec_rot) 

500 

501 def test_a_rotation_of_180(self): 

502 vec = (1, 0, 0) 

503 vec_rot = qrot_yaw(vec, 180) 

504 assert np.allclose([-1, 0, 0], vec_rot) 

505 

506 def test_a_full_rotation(self): 

507 vec = (1, 0, 0) 

508 vec_rot = qrot_yaw(vec, 360) 

509 assert np.allclose([1, 0, 0], vec_rot) 

510 

511 def test_a_rotation_of_45(self): 

512 vec = (1, 0, 0) 

513 vec_rot = qrot_yaw(vec, 45) 

514 assert np.allclose([0.7071, 0.7071, 0], vec_rot) 

515 

516 

517class TestIntersect3D(TestCase): 

518 def test_intersection_at_zero(self): 

519 p1 = np.array([(1, 0, 0), (0, 0, 1)]) 

520 p2 = -p1 

521 intersection = intersect_3d(p1, p2) 

522 assert np.allclose([0, 0, 0], intersection) 

523 

524 def test_intersection_of_multiple_lines_with_same_endpoints(self): 

525 p1 = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)]) 

526 p2 = np.array([(4, 4, 4), (4, 4, 4), (4, 4, 4)]) 

527 intersection = intersect_3d(p1, p2) 

528 assert np.allclose([4, 4, 4], intersection) 

529 

530 def test_intersection_of_multiple_lines_with_target(self): 

531 p1 = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)]) 

532 target = np.array([23, 5, 42]) 

533 p2 = 2 * target - p1 

534 intersection = intersect_3d(p1, p2) 

535 assert np.allclose(target, intersection) 

536 

537 def test_another_intersection(self): 

538 p1 = np.array([(1, 10, 0), (0, 10, 1)]) 

539 p2 = np.array([(-1, 10, 0), (0, 10, -1)]) 

540 intersection = intersect_3d(p1, p2) 

541 assert np.allclose([0, 10, 0], intersection) 

542 

543 

544class TestDist(TestCase): 

545 def test_dist_between_two_2D_points(self): 

546 self.assertAlmostEqual(1, dist(np.array([0, 0]), np.array([1, 0]))) 

547 self.assertAlmostEqual(np.sqrt(2), dist(np.array([0, 1]), np.array([1, 0]))) 

548 self.assertAlmostEqual(2 * np.sqrt(2), dist(np.array([1, 2]), np.array([3, 4]))) 

549 

550 def test_dist_between_two_3D_points(self): 

551 self.assertAlmostEqual(1, dist(np.array([0, 0, 0]), np.array([1, 0, 0]))) 

552 self.assertAlmostEqual( 

553 np.sqrt(2), dist(np.array([0, 1, 0]), np.array([1, 0, 0])) 

554 ) 

555 self.assertAlmostEqual(2, dist(np.array([0, 0, 2]), np.array([0, 0, 0]))) 

556 self.assertAlmostEqual( 

557 5.1961524, dist(np.array([1, 2, 3]), np.array([4, 5, 6])) 

558 ) 

559 

560 def test_dist_to_many_points(self): 

561 assert np.allclose( 

562 [1, 1, 0, 1.73205081], 

563 dist( 

564 np.array([0, 0, 0]), 

565 np.array([[0, 0, 1], [0, 0, 1], [0, 0, 0], [1, 1, 1]]), 

566 axis=1, 

567 ), 

568 )