1 module daque.math.geometry;
2 
3 import std.math;
4 
5 void geometryTest()
6 {
7 	import std.stdio;
8 	writeln("daque geometry correctly linked");
9 }
10 
11 /++
12     Mathematical dot product
13 +/
14 R dot(R)(R[] v, R[] w)
15 in
16 {
17     assert(v.length == w.length, "Dot product can only be applied between to vectors of the same dimension");
18 }
19 out
20 {
21 
22 }
23 do
24 {
25 	import std.array;
26 	import std.algorithm;
27 
28 	R[] products;
29 	products.length = v.length;
30 	products[] = v[] * w[];
31 	return products.array.sum;
32 }
33 
34 /++
35 	Mathematical distance between to points
36 +/
37 real distance(R)(R[] v, R[] w)
38 in
39 {
40 	assert(v.length == w.length, "distance can only be calculated between same-dimensional vectors");
41 }
42 out
43 {
44 }
45 do
46 {
47 	R[] diff;
48 	diff.length = v.length;
49 	diff[] = w[] - v[];
50 	return magnitude(diff);
51 }
52 
53 /++
54     Mathematical cross product
55 +/
56 R[] cross(R)(R[] v, R[] w)
57 in
58 {
59     assert(v.length == 3 && w.length == 3, "Cross product can only be applied between 3d vectors");
60 }
61 out (result)
62 {
63     R[] resultDup = result.dup;
64     assert(approxEqual(dot(resultDup, v), 0.0) && approxEqual(dot(resultDup, w), 0.0), "Cross product was not orthogonal to it's operands");
65 }
66 do
67 {
68     R[] result;
69     result.length = 3;
70     for(uint i; i < 3; i++)
71     {
72         int j = (i + 1) % 3; 
73         int k = (j + 1) % 3;
74         result[i] = v[j] * w[k] - v[k] * w[j];
75     }
76     return result;
77 }
78 
79 R magnitudeSquared(R)(R[] v)
80 out(result)
81 {
82 	assert(result >= 0);
83 }
84 do
85 {
86 	return dot(v, v);
87 }
88 
89 real magnitude(R)(R[] v)
90 {
91 	return sqrt(cast(real)magnitudeSquared(v));
92 }
93 
94 R[] normalize(R)(R[] v)
95 in
96 {
97 	assert(magnitudeSquared(v) != 0, "Cannot normalize a zero vector");
98 }
99 out(result)
100 {
101 	assert(approxEqual(magnitudeSquared(result.dup), 1), "Normalized vector wasn't unitary");
102 }
103 do
104 {
105 	R[] normalized;
106 	normalized.length = v.length;
107 	normalized[] = v[] / magnitude(v);
108 	return normalized;
109 }
110 
111 unittest
112 {
113 	assert(distance([0.0, 0.0], [0.5, 0.5]) != 0.0);
114 }