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 }