1 module math.linear.point;
2 
3 import math.linear.vector: Vec;
4 import vector_ = math.linear.vector;
5 
6 // TODO: Add tests to ensure T is a compotable type (number or vector, etc...).
7 struct Point(T) {
8 	union {
9 		T vector;
10 		struct {
11 			static if (T.data.length>=1)
12 				T.Type x;
13 			static if (T.data.length>=2)
14 				T.Type y;
15 			static if (T.data.length>=3)
16 				T.Type z;
17 			static if (T.data.length>=4)
18 				T.Type w;
19 		}
20 	}
21 	alias v = vector;
22 	
23 	const
24 	auto castType(NT)() {
25 		return point(vector.castType!NT);
26 	}
27 	
28 	const
29 	auto opBinary(string op, T)(T b) {////if (__traits(compiles, opBinaryImpl!op(this, b))){
30 		return opBinaryImpl!op(this, b);
31 	}
32 	const
33 	auto opBinaryRight(string op, T)(T a) if (__traits(compiles, opBinaryImpl!op(a, this))){
34 		return opBinaryImpl!op(a,this);
35 	}
36 	auto opOpAssign(string op, T)(T b) if (__traits(compiles, opOpAssignImpl!op(this, b))){
37 		return opOpAssignImpl!op(this, b);
38 	}
39 }
40 auto point(T)(T v) {
41 	return Point!T(v);
42 }
43 auto pvec(T, size_t size)(T[size] data ...) {
44 	return point(Vec!(T, size)(data));
45 }
46 auto pvec(size_t size, T)(T data) {
47 	return point(Vec!(T, size)(data));
48 }
49 
50 auto distance(T, U, size_t size)(Point!(Vec!(T,size)) v, Point!(Vec!(U,size)) w) {
51 	return vector_.distance(v.vector, w.vector);
52 }
53 
54 alias P = Point;
55 alias PVec(size_t size, T) = P!(Vec!(T, size));
56 alias PVec2(T) = P!(Vec!(T, 2));
57 alias PVec3(T) = P!(Vec!(T, 3));
58 alias PVec4(T) = P!(Vec!(T, 4));
59 
60 auto opBinaryImpl(string op:"-", T,U)(const P!T a, const P!U b) 
61 ////if	( __traits(compiles, mixin("a.vector"~op~"b.vector"))
62 ////	)
63 {
64 	return mixin("a.vector"~op~"b.vector");
65 }
66 auto opBinaryImpl(string op, T,U)(const P!T a, const U b) 
67 if	(__traits(compiles, mixin("a.vector"~op~"b"))
68 	&& (op=="-" || op=="+")
69 	)
70 {
71 	return point(mixin("a.vector"~op~"b"));
72 }
73 
74 auto opOpAssignImpl(string op, T,U)(ref P!T a, const U b) 
75 if	( __traits(compiles, mixin("a.vector"~op~"=b"))
76 	&& (op=="-" || op=="+")
77 	)
78 {
79 	mixin("a.vector"~op~"=b;");
80 	return a;
81 }
82