1 module math.geometry.line; 2 3 import math.linear.vector; 4 import math.linear.point; 5 import vec_ = math.linear.vector; 6 import point_ = math.linear.point; 7 8 alias PointLine = PointPointLine; 9 alias PPLine = PointPointLine; 10 struct PointPointLine(T) { 11 PVec2!T pointA; alias a=pointA; 12 PVec2!T pointB; alias b=pointB; 13 14 PointVecLine!T opCast(_:PointVecLine!T)() { 15 return VecLine!T(pointA,pointB-pointA); 16 } 17 } 18 alias VecLine = PointVecLine; 19 alias PVLine = PointVecLine; 20 struct PointVecLine(T) { 21 PVec2!T pos; alias point=pos; alias p=pos; 22 Vec2!T vector; alias vec=vector; alias v=vector; alias offset=vector; 23 24 PointPointLine!T opCast(_:PointPointLine!T)() { 25 return PointLine!T(pos,pos+vec); 26 } 27 } 28 29 30 T distance(T)(Point!(Vec!(T,2)) p, VecLine!T l) { 31 import std.algorithm.comparison; 32 import std.math; 33 auto ms = l.vec.magnitudeSquared; 34 if (ms == 0) 35 return (cast(T) sqrt(cast(real) ms)).abs; 36 auto t = max(0, min(1, dot(p - l.pos, l.vec) / ms)); 37 auto projection = l.pos + t*l.vec; 38 return vec_.distance(p.v, projection.v); 39 } 40 T distance(T)(VecLine!T l, Point!(Vec!(T,2)) p) { 41 return distance(p,l); 42 } 43 T distance(T)(Point!(Vec!(T,2)) p, PointLine!T l) { 44 return distance!T(p, cast(VecLine!T) l); 45 } 46 T distance(T)(PointLine!T l, Point!(Vec!(T,2)) p) { 47 return distance(p, cast(VecLine!T) l); 48 } 49 50 /// This does not work when two lines cross. 51 /// TODO: Make this work for when two lines cross. 52 /// TODO: This needs optimized. 53 T distance(T)(VecLine!T l, VecLine!T m) { 54 import std.algorithm.comparison; 55 return min( 56 distance(l.pos ,m), 57 distance(l.pos+l.vec ,m), 58 distance(m.pos ,l), 59 distance(m.pos+m.vec ,l), 60 ); 61 } 62 /// Ditto 63 T distance(T)(PointLine!T l, PointLine!T m) { 64 import std.algorithm.comparison; 65 return min( 66 distance(l.a ,m), 67 distance(l.b ,m), 68 distance(m.a ,l), 69 distance(m.b ,l), 70 ); 71 } 72 73 74 @("Point Line Distance") 75 unittest { 76 assert(distance(pvec(1f,0f), PPLine!float(pvec(0f,1f),pvec(0f,-1f)))==1f); 77 assert(distance(pvec(-1f,0f), PPLine!float(pvec(0f,1f),pvec(0f,-1f)))==1f); 78 assert(distance(pvec(1f,0f), PPLine!float(pvec(0f,-1f),pvec(0f,1f)))==1f); 79 assert(distance(pvec(1f,2f), PPLine!float(pvec(0f,1f),pvec(0f,-1f)))==vec_.distance(vec(1f,2f), vec(0f,1f))); 80 } 81 @("Line Line Distance") 82 unittest { 83 assert(distance(PPLine!float(pvec(1f,0f), pvec(2f,0f)), PPLine!float(pvec(0f,1f),pvec(0f,-1f)))==1f); 84 } 85