1 module tests.circle;
2 
3 import tests.utils;
4 import vivaldi;
5 
6 /**
7  * Generates an NxN matrix with a nodes evenly distributed around a
8  * circle with the given radius, and an additional node at the center
9  * of the circle, one extra radius away from the others.
10  *
11  * The extra radius should cause the central node to have a larger
12  * "height" than the others.
13  */
14 template circle(size_t n, double radius) {
15 
16     import std.math;
17 
18     auto circle() nothrow @safe @nogc {
19         auto matrix = matrix!n;
20 
21         for (size_t i = 0; i < n; i++) {
22             for (size_t j = i + 1; j < n; j++) {
23                 double rtt;
24 
25                 if (i == 0) {
26                     rtt = 2 * radius;
27                 } else {
28                     const t1 = 2.0 * PI * i / n;
29                     const x1 = cos(t1);
30                     const y1 = sin(t1);
31 
32                     const t2 = 2.0 * PI * j / n;
33                     const x2 = cos(t2);
34                     const y2 = sin(t2);
35 
36                     const dx = x2 - x1;
37                     const dy = y2 - y1;
38 
39                     const dist = hypot(dx, dy);
40 
41                     rtt = dist * radius;
42                 }
43 
44                 matrix[i][j] = rtt;
45                 matrix[j][i] = rtt;
46             }
47         }
48 
49         return matrix;
50     }
51 }
52 
53 @("circle")
54 unittest {
55     import std.format;
56     import std.random;
57 
58     // Stable seed for random unitvectors.
59     rndGen().seed(1);
60 
61     alias N = Node!(Coordinate!2, 20);
62 
63     immutable radius = 0.1;
64     immutable n = 25;
65     immutable cycles = 1000;
66 
67     N[n] nodes = new N[n];
68     double[n][n] matrix = circle!(n, radius);
69     simulate!(N, 3, n)(nodes, matrix, cycles);
70     auto stats = evaluate!(N, n)(nodes, matrix);
71 
72     foreach (i, node; nodes) {
73         auto c = node.coordinate;
74 
75         if (i == 0) {
76             assert(c.height >= 0.97 * radius,
77                    format("height=%s", c.height));
78         } else {
79             assert(c.height <= 0.03 * radius,
80                    format("height=%s", c.height));
81         }
82     }
83 
84     assert(stats.mean <= 0.0086, format("mean=%s", stats.mean));
85     assert(stats.max <= 0.12, format("max=%s", stats.max));
86 }