1 module vertex; 2 import math=std.math; 3 import std.stdio; 4 5 /** 6 A range of reals, mainly used for 1d intersection testing. 7 */ 8 struct Range 9 { 10 /// start of range 11 real start; 12 13 ///stop of range 14 real stop; 15 16 /** 17 checks if two ranges overlap and return the smallest offset that would make 18 them not overlap. 19 */ 20 real overlap(Range other) 21 { 22 real m1=(this.start+this.stop)/2; 23 real r1=math.abs(this.start-this.stop)/2; 24 25 real m2=(other.start+other.stop)/2; 26 real r2=math.abs(other.start-other.stop)/2; 27 28 if(math.abs(m1-m2)<(r1+r2)) 29 { 30 real offset=(r1+r2)-math.abs(m1-m2); 31 if(m1<m2) 32 return -offset; 33 return offset; 34 } 35 return 0; 36 } 37 38 /// 39 unittest 40 { 41 Range r1=Range(0,32); 42 Range r2=Range(16,48); 43 44 assert(r1.overlap(r2)==-16); 45 assert(r2.overlap(r1)==16); 46 } 47 48 /** 49 check if offset lies inside this range and returns the smallest offset 50 needed to make it lie outside this range. 51 */ 52 real overlap(real offset) 53 { 54 if (offset<start || offset>stop) 55 return 0; 56 real offs1=start-offset; 57 real offs2=stop-offset; 58 if(math.abs(offs1)<math.abs(offs2)) 59 return offs1; 60 else 61 return offs2; 62 } 63 64 /// 65 unittest 66 { 67 Range r1=Range(0,32); 68 assert(r1.overlap(8)==-8); 69 assert(r1.overlap(24)==8); 70 } 71 } 72 73 /** 74 A location in 2d space 75 */ 76 struct Vertex 77 { 78 /// 79 real x; 80 /// 81 real y; 82 Vector opBinary(string op)(Vertex rhs) 83 { 84 static if(op=="-") 85 { 86 Vector v={x-rhs.x,y-rhs.y}; 87 return v; 88 } 89 else static assert(0, "Operator "~op~" not implemented"); 90 } 91 92 Vertex opBinary(string op)(Vector rhs) 93 { 94 mixin("Vertex v={x"~op~"rhs.x,y"~op~"rhs.y};"); 95 return v; 96 } 97 98 } 99 100 /** 101 a vector in 2d space 102 */ 103 struct Vector 104 { 105 /// 106 real x; 107 /// 108 real y; 109 110 Vector opBinary(string op)(real rhs) 111 { 112 mixin("Vector v={x"~op~"rhs,y"~op~"rhs};"); 113 return v; 114 } 115 Vector opBinary(string op)(Vector rhs) 116 { 117 mixin("Vector v={x"~op~"rhs.x,y"~op~"rhs.y};"); 118 return v; 119 } 120 121 unittest 122 { 123 Vector a=Vector(1,2); 124 Vector b=Vector(3,4); 125 Vector c=a+b; 126 assert(c.x==4); 127 assert(c.y==6); 128 } 129 130 /** 131 return the scalar projection of this vector onto other vector 132 */ 133 real project_scalar(Vector other) 134 { 135 return this.dot(other.unit); 136 } 137 138 /// 139 unittest 140 { 141 Vector v1=Vector(1,0); 142 Vector v2=Vector(0,1); 143 144 assert(v2.project_scalar(v1)==0); 145 assert(v1.project_scalar(v2)==0); 146 assert(v1.project_scalar(v1)==1); 147 assert(v2.project_scalar(v2)==1); 148 } 149 150 /** 151 return the vector projection of this vector onto other vector 152 */ 153 Vector project(Vector other) 154 { 155 return other.unit*this.project_scalar(other); 156 } 157 158 /// 159 unittest 160 { 161 Vector v1=Vector(1,0); 162 Vector v2=Vector(0,1); 163 164 assert(v2.project(v1)==Vector(0,0)); 165 assert(v1.project(v2)==Vector(0,0)); 166 assert(v1.project(v1)==v1); 167 assert(v2.project(v2)==v2); 168 } 169 170 /** 171 return the dot product of this vector and other vector 172 */ 173 real dot(Vector other) 174 { 175 return this.x*other.x+this.y*other.y; 176 } 177 178 @property 179 { 180 ///true if this vector has a length of exactly zero 181 bool zero() 182 { 183 return (this.x==0&&this.y==0); 184 } 185 } 186 187 /// 188 unittest 189 { 190 Vector v1=Vector(0,0); 191 Vector v2=Vector(7,2); 192 193 assert(v1.zero==true); 194 assert(v2.zero==false); 195 } 196 197 ///vector magnitude 198 real length() 199 { 200 return math.sqrt(this.dot(this)); 201 } 202 203 /// 204 unittest 205 { 206 Vector v1=Vector(0,0); 207 Vector v2=Vector(5,0); 208 209 assert(v1.length==0); 210 assert(v2.length==5); 211 } 212 213 ///unit vector of this vector 214 Vector unit() 215 { 216 real ln=this.length; 217 Vector v={this.x/ln,this.y/ln}; 218 return v; 219 } 220 221 /// 222 unittest 223 { 224 Vector v1=Vector(5,0); 225 assert(v1.unit==Vector(1,0)); 226 } 227 228 ///this vector rotated 90 degrees 229 Vector rot90() 230 { 231 return Vector(-this.y,this.x); 232 } 233 234 /// 235 unittest 236 { 237 Vector v1=Vector(5,0); 238 assert(v1.rot90==Vector(0,5)); 239 assert(v1.rot90.rot90==Vector(-5,0)); 240 assert(v1.rot90.rot90.rot90==Vector(0,-5)); 241 assert(v1.rot90.rot90.rot90.rot90==v1); 242 } 243 }