Mercurial > projects > doodle
comparison import/geometry.d @ 0:e907d2c54ec3
Initial import
author | David Bryant <daveb@acres.com.au> |
---|---|
date | Wed, 13 May 2009 15:42:39 +0930 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e907d2c54ec3 |
---|---|
1 module interaction.geometry; | |
2 | |
3 private import std.math; | |
4 | |
5 private const double EPSILON = 1e-20; | |
6 | |
7 final class Point { | |
8 this() { | |
9 this(0.0, 0.0); | |
10 } | |
11 | |
12 this(double x, double y) { | |
13 _x = x; | |
14 _y = y; | |
15 } | |
16 | |
17 char[] toString() { | |
18 return "(" ~ std.string.toString(_x) ~ ", " ~ std.string.toString(_y) ~ ")"; | |
19 } | |
20 | |
21 Point opAdd(in Vector v) { | |
22 return new Point(_x + v._x, _y + v._y); | |
23 } | |
24 | |
25 Vector opSub(in Point p) { | |
26 return new Vector(_x - p._x, _y - p._y); | |
27 } | |
28 | |
29 double x() { return _x; } | |
30 double y() { return _y; } | |
31 | |
32 private { | |
33 double _x; | |
34 double _y; | |
35 } | |
36 } | |
37 | |
38 // | |
39 | |
40 final class Vector { | |
41 this() { | |
42 this(0.0, 0.0); | |
43 } | |
44 | |
45 this(double x, double y) { | |
46 _x = x; | |
47 _y = y; | |
48 } | |
49 | |
50 char[] toString() { | |
51 return "[" ~ std.string.toString(_x) ~ ", " ~ std.string.toString(_y) ~ "]"; | |
52 } | |
53 | |
54 Vector opAdd(in Vector v) { | |
55 return new Vector(_x + v._x, _y + v._y); | |
56 } | |
57 | |
58 Vector opSub(in Vector v) { | |
59 return new Vector(_x - v._x, _y - v._y); | |
60 } | |
61 | |
62 Vector opNeg() { | |
63 return new Vector(-_x, -_y); | |
64 } | |
65 | |
66 Vector opMul_r(double d) { | |
67 return new Vector(d * _x, d * _y); | |
68 } | |
69 | |
70 double length() { | |
71 return sqrt(_x * _x + _y * _y); | |
72 } | |
73 | |
74 bool has_length() { | |
75 return _x * _x + _y * _y > EPSILON * EPSILON; | |
76 } | |
77 | |
78 double x() { return _x; } | |
79 double y() { return _y; } | |
80 | |
81 private { | |
82 double _x; | |
83 double _y; | |
84 } | |
85 } | |
86 | |
87 // | |
88 | |
89 final class Segment { | |
90 this() { | |
91 } | |
92 | |
93 this(Point start, Point end) { | |
94 _start = start; | |
95 _end = end; | |
96 } | |
97 | |
98 Point start() { return _start; } | |
99 Point end() { return _end; } | |
100 | |
101 private { | |
102 Point _start; | |
103 Point _end; | |
104 } | |
105 } | |
106 | |
107 // | |
108 | |
109 final class Line { | |
110 this() { | |
111 } | |
112 | |
113 this(Point point, Vector vector) { | |
114 assert(vector.has_length); | |
115 _point = point; | |
116 _vector = vector; | |
117 } | |
118 | |
119 this(Point point1, Point point2) { | |
120 _point = point1; | |
121 _vector = point2 - point1; | |
122 assert(_vector.has_length); | |
123 } | |
124 | |
125 private { | |
126 Point _point; | |
127 Vector _vector; | |
128 } | |
129 } | |
130 | |
131 // | |
132 | |
133 final class Rectangle { | |
134 this() { | |
135 this(0.0, 0.0, 0.0, 0.0); | |
136 } | |
137 | |
138 this(double x, double y, double w, double h) { | |
139 assert(w >= 0.0); | |
140 assert(h >= 0.0); | |
141 _x = x; | |
142 _y = y; | |
143 _w = w; | |
144 _h = h; | |
145 } | |
146 | |
147 double x() { return _x; } | |
148 double y() { return _y; } | |
149 double w() { return _w; } | |
150 double h() { return _h; } | |
151 double xw() { return _x + _w; } | |
152 double yh() { return _y + _h; } | |
153 | |
154 /* | |
155 Point corner00() { return new Point(_x, _y ); } | |
156 Point corner10() { return new Point(_x + _w, _y ); } | |
157 Point corner11() { return new Point(_x + _w, _y + _h); } | |
158 Point corner01() { return new Point(_x, _y + _h); } | |
159 | |
160 Point centre() { return new Point(_x + _w / 2.0, _y + _h / 2.0); } | |
161 */ | |
162 | |
163 double area() { | |
164 return _w * _h; | |
165 } | |
166 | |
167 bool has_area() { | |
168 return area > 0.0; | |
169 } | |
170 | |
171 bool contains(Point point) { | |
172 return point.x > x && point.x < xw & point.y > y && point.y < xy; | |
173 } | |
174 | |
175 bool contains(Segment segment) { | |
176 return contains(segment.start, segment.end); | |
177 } | |
178 | |
179 private double _x, _y, _w, _h; | |
180 } | |
181 | |
182 unittest { | |
183 const double absdiff = 1e-20, reldiff= 1e-20; | |
184 | |
185 bool cmpdouble(in double lhs, in double rhs) { | |
186 double adiff = fabs(rhs - lhs); | |
187 | |
188 if (adiff < absdiff && adiff > -absdiff) { | |
189 return true; | |
190 } | |
191 | |
192 if (fabs(lhs) > absdiff && fabs(rhs) > absdiff) { | |
193 double rdiff = rhs / lhs; | |
194 | |
195 if (rdiff < (1.0 + reldiff) && rdiff > 1.0 / (1.0 + reldiff)) { | |
196 return true; | |
197 } | |
198 } | |
199 | |
200 // They must differ significantly | |
201 | |
202 return false; | |
203 } | |
204 | |
205 bool cmpvector(in Vector lhs, in Vector rhs) { | |
206 return cmpdouble(lhs._x, rhs._x) && cmpdouble(lhs._y, rhs._y); | |
207 } | |
208 | |
209 bool cmppoint(in Point lhs, in Point rhs) { | |
210 return cmpdouble(lhs._x, rhs._x) && cmpdouble(lhs._y, rhs._y); | |
211 } | |
212 | |
213 assert(cmpvector(new Vector(0.0, 0.0), new Vector)); | |
214 assert(!cmpvector(new Vector(0.0, 1e-10), new Vector)); | |
215 assert(cmpvector(new Vector(1.0, 2.0) + new Vector(3.0, 4.0), new Vector(4.0, 6.0))); | |
216 assert(cmpvector(new Vector(1.0, 2.0) - new Vector(3.0, 4.0), new Vector(-2.0, -2.0))); | |
217 assert(cmpvector(-(new Vector(1.0, 2.0)), new Vector(-1.0, -2.0))); | |
218 assert(cmpdouble((new Vector(3.0, 4.0)).length(), 5.0)); | |
219 assert(cmpvector(3.0 * (new Vector(3.0, 4.0)), new Vector(9.0, 12.0))); | |
220 } |