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     }