| 1 | import sys |
|---|
| 2 | |
|---|
| 3 | from numpy import random |
|---|
| 4 | import numpy as np |
|---|
| 5 | |
|---|
| 6 | from scikits import delaunay as dlny |
|---|
| 7 | |
|---|
| 8 | def onright(x0, y0, x1, y1, x, y): |
|---|
| 9 | """Return True if (x,y) is to the right of the vector from (x0,y0) to |
|---|
| 10 | (x1,y1). |
|---|
| 11 | """ |
|---|
| 12 | return (y0-y)*(x1-x) > (x0-x)*(y1-y) |
|---|
| 13 | |
|---|
| 14 | def incircle(cx, cy, r, x, y): |
|---|
| 15 | """Return True if (x,y) is strictly inside the circle centered at (cx,cy) |
|---|
| 16 | with radius r. |
|---|
| 17 | """ |
|---|
| 18 | r2 = np.hypot(x-cx, y-cy) |
|---|
| 19 | assert r2 < r |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | class TestSanity(object): |
|---|
| 23 | def setup(self): |
|---|
| 24 | self.rs = random.RandomState(1234567890) |
|---|
| 25 | |
|---|
| 26 | def test_counts(self): |
|---|
| 27 | for n in (10, 30, 100, 300, 1000, 3000): |
|---|
| 28 | x, y = self.rs.uniform(0, 1, size=(2, n)) |
|---|
| 29 | tri = dlny.Triangulation(x, y) |
|---|
| 30 | k = len(tri.hull) |
|---|
| 31 | ntriangles = 2*n - 2 - k |
|---|
| 32 | nedges = 3*n - 3 - k |
|---|
| 33 | assert tri.triangle_nodes.shape == (ntriangles, 3) |
|---|
| 34 | assert tri.triangle_neighbors.shape == (ntriangles, 3) |
|---|
| 35 | assert tri.edge_db.shape == (nedges, 2) |
|---|
| 36 | assert tri.circumcenters.shape == (ntriangles, 2) |
|---|
| 37 | assert np.sum((tri.triangle_neighbors == -1).astype(np.int32).flat) == k |
|---|
| 38 | |
|---|
| 39 | def test_ccw_triangles(self): |
|---|
| 40 | for n in (10, 30, 100, 300, 1000, 3000): |
|---|
| 41 | x, y = self.rs.uniform(0, 1, size=(2, n)) |
|---|
| 42 | tri = dlny.Triangulation(x, y) |
|---|
| 43 | |
|---|
| 44 | for i,j,k in tri.triangle_nodes: |
|---|
| 45 | assert not onright(x[i], y[i], x[j], y[j], x[k], y[k]) |
|---|
| 46 | |
|---|
| 47 | def test_ccw_hull(self): |
|---|
| 48 | for n in (10, 30, 100, 300, 1000, 3000): |
|---|
| 49 | x, y = self.rs.uniform(0, 1, size=(2, n)) |
|---|
| 50 | tri = dlny.Triangulation(x, y) |
|---|
| 51 | |
|---|
| 52 | hull = list(tri.hull) |
|---|
| 53 | hull.append(hull[0]) |
|---|
| 54 | hull.append(hull[1]) |
|---|
| 55 | |
|---|
| 56 | for i,j,k in zip(hull[:-2], hull[1:-1], hull[2:]): |
|---|
| 57 | assert not onright(x[i], y[i], x[j], y[j], x[k], y[k]) |
|---|
| 58 | |
|---|
| 59 | def test_circle_condition(self): |
|---|
| 60 | assert False, "doesn't work perfectly given floating point imprecision" |
|---|
| 61 | for n in (10, 30, 100, 300, 1000, 3000): |
|---|
| 62 | x, y = self.rs.uniform(0, 1, size=(2, n)) |
|---|
| 63 | tri = dlny.Triangulation(x, y) |
|---|
| 64 | |
|---|
| 65 | i = tri.triangle_nodes[:,0] |
|---|
| 66 | r2 = ((x[i] - tri.circumcenters[:,0])**2 |
|---|
| 67 | + (y[i] - tri.circumcenters[:,1])**2) |
|---|
| 68 | alldist2 = (np.subtract.outer(x, tri.circumcenters[:,0])**2 |
|---|
| 69 | + np.subtract.outer(y, tri.circumcenters[:,1])**2) |
|---|
| 70 | good = (r2 <= (alldist2 + 1e-12)) |
|---|
| 71 | assert np.alltrue(good) |
|---|
| 72 | |
|---|
| 73 | |
|---|
| 74 | data = np.array([ |
|---|
| 75 | [-3.14, -3.14], [-3.14, -2.36], [-3.14, -1.57], [-3.14, -0.79], [-3.14, 0.0], |
|---|
| 76 | [-3.14, 0.79], [-3.14, 1.57], [-3.14, 2.36], [-3.14, 3.14], [-2.36, -3.14], |
|---|
| 77 | [-2.36, -2.36], [-2.36, -1.57], [-2.36, -0.79], [-2.36, 0.0], [-2.36, 0.79], |
|---|
| 78 | [-2.36, 1.57], [-2.36, 2.36], [-2.36, 3.14], [-1.57, -0.79], [-1.57, 0.79], |
|---|
| 79 | [-1.57, -1.57], [-1.57, 0.0], [-1.57, 1.57], [-1.57, -3.14], [-1.57, -2.36], |
|---|
| 80 | [-1.57, 2.36], [-1.57, 3.14], [-0.79, -1.57], [-0.79, 1.57], [-0.79, -3.14], |
|---|
| 81 | [-0.79, -2.36], [-0.79, -0.79], [-0.79, 0.0], [-0.79, 0.79], [-0.79, 2.36], |
|---|
| 82 | [-0.79, 3.14], [0.0, -3.14], [0.0, -2.36], [0.0, -1.57], [0.0, -0.79], |
|---|
| 83 | [0.0, 0.0], [0.0, 0.79], [0.0, 1.57], [0.0, 2.36], [0.0, 3.14], |
|---|
| 84 | [0.79, -3.14], [0.79, -2.36], [0.79, -0.79], [0.79, 0.0], [0.79, 0.79], |
|---|
| 85 | [0.79, 2.36], [0.79, 3.14], [0.79, -1.57], [0.79, 1.57], [1.57, -3.14], |
|---|
| 86 | [1.57, -2.36], [1.57, 2.36], [1.57, 3.14], [1.57, -1.57], [1.57, 0.0], |
|---|
| 87 | [1.57, 1.57], [1.57, -0.79], [1.57, 0.79], [2.36, -3.14], [2.36, -2.36], |
|---|
| 88 | [2.36, -1.57], [2.36, -0.79], [2.36, 0.0], [2.36, 0.79], [2.36, 1.57], |
|---|
| 89 | [2.36, 2.36], [2.36, 3.14], [3.14, -3.14], [3.14, -2.36], [3.14, -1.57], |
|---|
| 90 | [3.14, -0.79], [3.14, 0.0], [3.14, 0.79], [3.14, 1.57], [3.14, 2.36], |
|---|
| 91 | [3.14, 3.14], |
|---|
| 92 | ]) |
|---|
| 93 | |
|---|
| 94 | class TestRegression(object): |
|---|
| 95 | |
|---|
| 96 | def test_ticket_376(self): |
|---|
| 97 | x = np.array([0, 1, 0, 1], dtype=np.float64) |
|---|
| 98 | y = np.array([0, 0, 1, 1], dtype=np.float64) |
|---|
| 99 | z = np.array([1, 2, 3, 4], dtype=np.float64) |
|---|
| 100 | |
|---|
| 101 | tri1 = dlny.Triangulation(x, y) |
|---|
| 102 | nn1 = tri1.nn_interpolator(z) |
|---|
| 103 | |
|---|
| 104 | xp = np.r_[x, x] |
|---|
| 105 | yp = np.r_[y, y] |
|---|
| 106 | zp = np.r_[z, z] |
|---|
| 107 | |
|---|
| 108 | # shouldn't fail on duplicate points |
|---|
| 109 | tri2 = dlny.Triangulation(xp, yp) |
|---|
| 110 | nn2 = tri2.nn_interpolator(zp) |
|---|
| 111 | |
|---|
| 112 | assert nn1(0.3, 0.5) == nn2(0.3, 0.5) |
|---|
| 113 | |
|---|
| 114 | def test_ticket_376_2(self): |
|---|
| 115 | tri = dlny.Triangulation(data[:,0], data[:,1]) |
|---|
| 116 | # should pass |
|---|
| 117 | |
|---|
| 118 | def test_ticket_382(self): |
|---|
| 119 | x, y = np.meshgrid(np.linspace(0,1,4), np.linspace(0,1,3)) |
|---|
| 120 | |
|---|
| 121 | tri = dlny.Triangulation(x.flatten(), y.flatten()) |
|---|
| 122 | refcount1 = sys.getrefcount(tri.x) |
|---|
| 123 | interp = tri.nn_interpolator(x.flatten()) |
|---|
| 124 | refcount2 = sys.getrefcount(tri.x) |
|---|
| 125 | interp(x.flatten(), y.flatten()) |
|---|
| 126 | refcount3 = sys.getrefcount(tri.x) |
|---|
| 127 | |
|---|
| 128 | # shouldn't leak references |
|---|
| 129 | assert refcount1 == refcount2 |
|---|
| 130 | assert refcount1 == refcount3 |
|---|
| 131 | |
|---|
| 132 | if __name__ == '__main__': |
|---|
| 133 | import nose |
|---|
| 134 | nose.main() |
|---|