Skip to content

Commit 110c651

Browse files
committed
add unit tests
1 parent 35d8ce5 commit 110c651

2 files changed

Lines changed: 366 additions & 0 deletions

File tree

‎tests/base/test_numeric.py‎

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on Fri Apr 10 14:19:04 2020
5+
6+
@author: corkep
7+
8+
"""
9+
10+
import numpy as np
11+
import numpy.testing as nt
12+
import unittest
13+
import math
14+
15+
16+
from spatialmath.base.numeric import *
17+
18+
19+
class TestNumeric(unittest.TestCase):
20+
def test_numjac(self):
21+
22+
pass
23+
24+
def test_array2str(self):
25+
26+
x = [1.2345678]
27+
s = array2str(x)
28+
29+
self.assertIsInstance(s, str)
30+
self.assertEqual(s, "[ 1.23 ]")
31+
32+
s = array2str(x, fmt="{:.5f}")
33+
self.assertEqual(s, "[ 1.23457 ]")
34+
35+
s = array2str([1, 2, 3])
36+
self.assertEqual(s, "[ 1, 2, 3 ]")
37+
38+
s = array2str([1, 2, 3], valuesep=":")
39+
self.assertEqual(s, "[ 1:2:3 ]")
40+
41+
s = array2str([1, 2, 3], brackets=("<< ", " >>"))
42+
self.assertEqual(s, "<< 1, 2, 3 >>")
43+
44+
s = array2str([1, 2e-8, 3])
45+
self.assertEqual(s, "[ 1, 2e-08, 3 ]")
46+
47+
s = array2str([1, -2e-14, 3])
48+
self.assertEqual(s, "[ 1, 0, 3 ]")
49+
50+
x = np.array([[1, 2, 3], [4, 5, 6]])
51+
s = array2str(x)
52+
self.assertEqual(s, "[ 1, 2, 3 | 4, 5, 6 ]")
53+
54+
def test_bresenham(self):
55+
56+
x, y = bresenham((-10, -10), (20, 10))
57+
self.assertIsInstance(x, np.ndarray)
58+
self.assertEqual(x.ndim, 1)
59+
self.assertIsInstance(y, np.ndarray)
60+
self.assertEqual(y.ndim, 1)
61+
self.assertEqual(len(x), len(y))
62+
63+
# test points are no more than sqrt(2) apart
64+
z = np.array([x, y])
65+
d = np.diff(z, axis=1)
66+
d = np.linalg.norm(d, axis=0)
67+
self.assertTrue(all(d <= np.sqrt(2)))
68+
69+
x, y = bresenham((20, 10), (-10, -10))
70+
71+
# test points are no more than sqrt(2) apart
72+
z = np.array([x, y])
73+
d = np.diff(z, axis=1)
74+
d = np.linalg.norm(d, axis=0)
75+
self.assertTrue(all(d <= np.sqrt(2)))
76+
77+
x, y = bresenham((-10, -10), (10, 20))
78+
79+
# test points are no more than sqrt(2) apart
80+
z = np.array([x, y])
81+
d = np.diff(z, axis=1)
82+
d = np.linalg.norm(d, axis=0)
83+
self.assertTrue(all(d <= np.sqrt(2)))
84+
85+
x, y = bresenham((10, 20), (-10, -10))
86+
87+
# test points are no more than sqrt(2) apart
88+
z = np.array([x, y])
89+
d = np.diff(z, axis=1)
90+
d = np.linalg.norm(d, axis=0)
91+
self.assertTrue(all(d <= np.sqrt(2)))
92+
93+
def test_mpq(self):
94+
95+
data = np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]])
96+
97+
self.assertEqual(mpq_point(data, 0, 0), 4)
98+
self.assertEqual(mpq_point(data, 1, 0), 0)
99+
self.assertEqual(mpq_point(data, 0, 1), 0)
100+
101+
def test_gauss1d(self):
102+
103+
x = np.arange(-10, 10, 0.02)
104+
y = gauss1d(2, 1, x)
105+
106+
self.assertEqual(len(x), len(y))
107+
108+
m = np.argmax(y)
109+
self.assertAlmostEqual(x[m], 2)
110+
111+
def test_gauss2d(self):
112+
113+
r = np.arange(-10, 10, 0.02)
114+
X, Y = np.meshgrid(r, r)
115+
Z = gauss2d([2, 3], np.eye(2), X, Y)
116+
117+
m = np.unravel_index(np.argmax(Z, axis=None), Z.shape)
118+
self.assertAlmostEqual(r[m[0]], 3)
119+
self.assertAlmostEqual(r[m[1]], 2)
120+
121+
122+
# ---------------------------------------------------------------------------------------#
123+
if __name__ == "__main__":
124+
125+
unittest.main()

‎tests/test_geom2d.py‎

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on Sun Jul 5 14:37:24 2020
5+
6+
@author: corkep
7+
"""
8+
9+
from spatialmath.geom2d import *
10+
from spatialmath.pose2d import SE2
11+
12+
import unittest
13+
import numpy.testing as nt
14+
import spatialmath.base as smb
15+
16+
17+
class Polygon2Test(unittest.TestCase):
18+
# Primitives
19+
def test_constructor1(self):
20+
p = Polygon2([(1, 2), (3, 2), (2, 4)])
21+
self.assertIsInstance(p, Polygon2)
22+
self.assertEqual(len(p), 3)
23+
self.assertEqual(str(p), "Polygon2 with 4 vertices")
24+
nt.assert_array_equal(p.vertices(), np.array([[1, 3, 2], [2, 2, 4]]))
25+
nt.assert_array_equal(
26+
p.vertices(unique=False), np.array([[1, 3, 2, 1], [2, 2, 4, 2]])
27+
)
28+
29+
def test_methods(self):
30+
p = Polygon2(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]]))
31+
32+
self.assertEqual(p.area(), 4)
33+
self.assertEqual(p.moment(0, 0), 4)
34+
self.assertEqual(p.moment(1, 0), 0)
35+
self.assertEqual(p.moment(0, 1), 0)
36+
nt.assert_array_equal(p.centroid(), np.r_[0, 0])
37+
38+
self.assertEqual(p.radius(), np.sqrt(2))
39+
nt.assert_array_equal(p.bbox(), np.r_[-1, -1, 1, 1])
40+
41+
def test_contains(self):
42+
p = Polygon2(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]]))
43+
self.assertTrue(p.contains([0, 0], radius=1e-6))
44+
self.assertTrue(p.contains([1, 0], radius=1e-6))
45+
self.assertTrue(p.contains([-1, 0], radius=1e-6))
46+
self.assertTrue(p.contains([0, 1], radius=1e-6))
47+
self.assertTrue(p.contains([0, -1], radius=1e-6))
48+
49+
self.assertFalse(p.contains([0, 1.1], radius=1e-6))
50+
self.assertFalse(p.contains([0, -1.1], radius=1e-6))
51+
self.assertFalse(p.contains([1.1, 0], radius=1e-6))
52+
self.assertFalse(p.contains([-1.1, 0], radius=1e-6))
53+
54+
self.assertTrue(p.contains(np.r_[0, -1], radius=1e-6))
55+
self.assertFalse(p.contains(np.r_[0, 1.1], radius=1e-6))
56+
57+
def test_transform(self):
58+
p = Polygon2(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]]))
59+
60+
p = p.transformed(SE2(2, 3))
61+
62+
self.assertEqual(p.area(), 4)
63+
self.assertEqual(p.moment(0, 0), 4)
64+
self.assertEqual(p.moment(1, 0), 8)
65+
self.assertEqual(p.moment(0, 1), 12)
66+
nt.assert_array_equal(p.centroid(), np.r_[2, 3])
67+
68+
def test_intersect(self):
69+
p1 = Polygon2(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]]))
70+
71+
p2 = p1.transformed(SE2(2, 3))
72+
self.assertFalse(p1.intersects(p2))
73+
74+
p2 = p1.transformed(SE2(1, 1))
75+
self.assertTrue(p1.intersects(p2))
76+
77+
self.assertTrue(p1.intersects(p1))
78+
79+
def test_intersect_line(self):
80+
p = Polygon2(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]]))
81+
82+
l = Line2.Join((-10, 0), (10, 0))
83+
self.assertTrue(p.intersects(l))
84+
85+
l = Line2.Join((-10, 1.1), (10, 1.1))
86+
self.assertFalse(p.intersects(l))
87+
88+
def test_plot(self):
89+
p = Polygon2(np.array([[-1, 1, 1, -1], [-1, -1, 1, 1]]))
90+
p.plot()
91+
92+
p.animate(SE2(1, 2))
93+
94+
def test_edges(self):
95+
p = Polygon2([(1, 2), (3, 2), (2, 4)])
96+
e = p.edges()
97+
98+
e = list(e)
99+
nt.assert_equal(e[0], ((1, 2), (3, 2)))
100+
nt.assert_equal(e[1], ((3, 2), (2, 4)))
101+
nt.assert_equal(e[2], ((2, 4), (1, 2)))
102+
103+
# p.move(SE2(0, 0, 0.7))
104+
105+
106+
class Line2Test(unittest.TestCase):
107+
def test_constructor(self):
108+
l = Line2([1, 2, 3])
109+
self.assertEqual(str(l), "Line2: [1. 2. 3.]")
110+
111+
l = Line2.Join((0, 0), (1, 2))
112+
nt.assert_equal(l.line, [-2, 1, 0])
113+
114+
l = Line2.General(2, 1)
115+
nt.assert_equal(l.line, [2, -1, 1])
116+
117+
def test_contains(self):
118+
l = Line2.Join((0, 0), (1, 2))
119+
120+
self.assertTrue(l.contains((0, 0)))
121+
self.assertTrue(l.contains((1, 2)))
122+
self.assertTrue(l.contains((2, 4)))
123+
124+
def test_intersect(self):
125+
l1 = Line2.Join((0, 0), (2, 0)) # y = 0
126+
l2 = Line2.Join((0, 1), (2, 1)) # y = 1
127+
self.assertFalse(l1.intersect(l2))
128+
129+
l2 = Line2.Join((2, 1), (2, -1)) # x = 2
130+
self.assertTrue(l1.intersect(l2))
131+
132+
def test_intersect_segment(self):
133+
l1 = Line2.Join((0, 0), (2, 0)) # y = 0
134+
self.assertFalse(l1.intersect_segment((2, 1), (2, 3)))
135+
self.assertTrue(l1.intersect_segment((2, 1), (2, -1)))
136+
137+
138+
class EllipseTest(unittest.TestCase):
139+
def test_constructor(self):
140+
E = np.array([[1, 1], [1, 3]])
141+
e = Ellipse(E=E)
142+
nt.assert_almost_equal(e.E, E)
143+
nt.assert_almost_equal(e.centre, [0, 0])
144+
self.assertAlmostEqual(e.theta, 1.1780972450961724)
145+
146+
e = Ellipse(radii=(1, 2), theta=0)
147+
nt.assert_almost_equal(e.E, np.diag([1, 0.25]))
148+
nt.assert_almost_equal(e.centre, [0, 0])
149+
nt.assert_almost_equal(e.radii, [1, 2])
150+
self.assertAlmostEqual(e.theta, 0)
151+
152+
e = Ellipse(radii=(1, 2), theta=np.pi / 2)
153+
nt.assert_almost_equal(e.E, np.diag([0.25, 1]))
154+
nt.assert_almost_equal(e.centre, [0, 0])
155+
nt.assert_almost_equal(e.radii, [2, 1])
156+
self.assertAlmostEqual(e.theta, np.pi / 2)
157+
158+
E = np.array([[1, 1], [1, 3]])
159+
e = Ellipse(E=E, centre=[3, 4])
160+
nt.assert_almost_equal(e.E, E)
161+
nt.assert_almost_equal(e.centre, [3, 4])
162+
self.assertAlmostEqual(e.theta, 1.1780972450961724)
163+
164+
e = Ellipse(radii=(1, 2), theta=0, centre=[3, 4])
165+
nt.assert_almost_equal(e.E, np.diag([1, 0.25]))
166+
nt.assert_almost_equal(e.centre, [3, 4])
167+
nt.assert_almost_equal(e.radii, [1, 2])
168+
self.assertAlmostEqual(e.theta, 0)
169+
170+
def test_Polynomial(self):
171+
e = Ellipse.Polynomial([2, 3, 1, 0, 0, -1])
172+
nt.assert_almost_equal(e.E, np.array([[2, 0.5], [0.5, 3]]))
173+
nt.assert_almost_equal(e.centre, [0, 0])
174+
175+
def test_FromPerimeter(self):
176+
eref = Ellipse(radii=(1, 2), theta=0, centre=[0, 0])
177+
p = eref.points()
178+
179+
e = Ellipse.FromPerimeter(p)
180+
nt.assert_almost_equal(e.radii, eref.radii)
181+
nt.assert_almost_equal(e.centre, eref.centre)
182+
nt.assert_almost_equal(e.theta, eref.theta)
183+
184+
##
185+
eref = Ellipse(radii=(1, 2), theta=0, centre=[3, 4])
186+
p = eref.points()
187+
188+
e = Ellipse.FromPerimeter(p)
189+
nt.assert_almost_equal(e.radii, eref.radii)
190+
nt.assert_almost_equal(e.centre, eref.centre)
191+
nt.assert_almost_equal(e.theta, eref.theta)
192+
193+
##
194+
eref = Ellipse(radii=(1, 2), theta=np.pi / 4, centre=[3, 4])
195+
p = eref.points()
196+
197+
e = Ellipse.FromPerimeter(p)
198+
# nt.assert_almost_equal(e.radii, eref.radii) # HACK
199+
nt.assert_almost_equal(e.centre, eref.centre)
200+
nt.assert_almost_equal(e.theta, eref.theta)
201+
202+
def test_FromPoints(self):
203+
eref = Ellipse(radii=(1, 2), theta=np.pi / 2, centre=(3, 4))
204+
rng = np.random.default_rng(0)
205+
206+
# create 200 random points inside the ellipse
207+
x = []
208+
while len(x) < 200:
209+
p = rng.uniform(low=1, high=6, size=(2, 1))
210+
if eref.contains(p):
211+
x.append(p)
212+
x = np.hstack(x) # create 2 x 50 array
213+
214+
e = Ellipse.FromPoints(x)
215+
nt.assert_almost_equal(e.radii, eref.radii, decimal=1)
216+
nt.assert_almost_equal(e.centre, eref.centre, decimal=1)
217+
nt.assert_almost_equal(e.theta, eref.theta, decimal=1)
218+
219+
def test_misc(self):
220+
e = Ellipse(radii=(1, 2), theta=np.pi / 2)
221+
self.assertIsInstance(str(e), str)
222+
223+
self.assertAlmostEqual(e.area, np.pi * 2)
224+
225+
e = Ellipse(radii=(1, 2), theta=0)
226+
self.assertTrue(e.contains((0, 0)))
227+
self.assertTrue(e.contains((1, 0)))
228+
self.assertTrue(e.contains((-1, 0)))
229+
self.assertTrue(e.contains((0, 2)))
230+
self.assertTrue(e.contains((0, -2)))
231+
232+
self.assertFalse(e.contains((1.1, 0)))
233+
self.assertFalse(e.contains((-1.1, 0)))
234+
self.assertFalse(e.contains((0, 2.1)))
235+
self.assertFalse(e.contains((0, -2.1)))
236+
237+
self.assertEqual(e.contains(np.array([[0, 0], [3, 3]]).T), [True, False])
238+
239+
240+
if __name__ == "__main__":
241+
unittest.main()

0 commit comments

Comments
 (0)