Mercurial > projects > doodle
comparison doodle/tk/geometry.d @ 41:f2e4e1d29b98
Bah
author | daveb |
---|---|
date | Tue, 01 Jun 2010 17:21:01 +0930 |
parents | 1f97022e5c6d |
children | 1b4c9ba58673 |
comparison
equal
deleted
inserted
replaced
40:1f97022e5c6d | 41:f2e4e1d29b98 |
---|---|
2 | 2 |
3 private { | 3 private { |
4 import std.stdio; | 4 import std.stdio; |
5 import std.math; | 5 import std.math; |
6 import doodle.tk.misc; | 6 import doodle.tk.misc; |
7 import doodle.core.logging; | |
7 } | 8 } |
8 | 9 |
9 // In doodle x and y increase right/east and up/north respectively. | 10 // In doodle x and y increase right/east and up/north respectively. |
10 | 11 |
11 // TODO explain the strategy for ensuring numerical stability | 12 // TODO explain the strategy for ensuring numerical stability |
28 static this() { | 29 static this() { |
29 DEFAULT = Point(0.0, 0.0); | 30 DEFAULT = Point(0.0, 0.0); |
30 } | 31 } |
31 | 32 |
32 this(in double x, in double y) { | 33 this(in double x, in double y) { |
34 assert(!isnan(x)); | |
35 assert(!isnan(y)); | |
33 _x = x; | 36 _x = x; |
34 _y = y; | 37 _y = y; |
35 } | 38 } |
36 | 39 |
37 Point opAdd(in Vector v) const { | 40 Point opAdd(in Vector v) const { |
76 static this() { | 79 static this() { |
77 DEFAULT = Vector(0.0, 0.0); | 80 DEFAULT = Vector(0.0, 0.0); |
78 } | 81 } |
79 | 82 |
80 this(in double x, in double y) { | 83 this(in double x, in double y) { |
84 assert(!isnan(x)); | |
85 assert(!isnan(y)); | |
81 _x = x; | 86 _x = x; |
82 _y = y; | 87 _y = y; |
83 } | 88 } |
84 | 89 |
85 Vector opAdd(in Vector v) const { | 90 Vector opAdd(in Vector v) const { |
93 Vector opNeg() const { | 98 Vector opNeg() const { |
94 return Vector(-_x, -_y); | 99 return Vector(-_x, -_y); |
95 } | 100 } |
96 | 101 |
97 Vector opMul_r(in double d) const { | 102 Vector opMul_r(in double d) const { |
103 assert(!isnan(d)); | |
98 return Vector(d * _x, d * _y); | 104 return Vector(d * _x, d * _y); |
99 } | 105 } |
100 | 106 |
101 Vector opDiv(in double d) const { | 107 Vector opDiv(in double d) const { |
108 assert(!isnan(d)); | |
102 return Vector(_x / d, _y / d); | 109 return Vector(_x / d, _y / d); |
103 } | 110 } |
104 | 111 |
105 double length() const { | 112 double length() const { |
106 return sqrt(_x * _x + _y * _y); | 113 return sqrt(_x * _x + _y * _y); |
162 | 169 |
163 Vector size() const { return _size; } | 170 Vector size() const { return _size; } |
164 | 171 |
165 Point max_corner() const { return _position + _size; } | 172 Point max_corner() const { return _position + _size; } |
166 | 173 |
167 bool valid() const { return _size.x > 0.0 & _size.y > 0.0; } | 174 bool valid() const { return _size.x > 0.0 && _size.y > 0.0; } |
168 | 175 |
169 bool invalid() const { return !valid(); } | 176 bool invalid() const { return !valid(); } |
170 | 177 |
171 double area() const { return _size.x * _size.y; } | 178 double area() const { return _size.x * _size.y; } |
172 | 179 |
243 | 250 |
244 Rectangle reposition(in Rectangle r, in Point new_position) { | 251 Rectangle reposition(in Rectangle r, in Point new_position) { |
245 return Rectangle(new_position, r.size); | 252 return Rectangle(new_position, r.size); |
246 } | 253 } |
247 | 254 |
255 Rectangle resize(in Rectangle r, in Vector new_size) { | |
256 return Rectangle(r.position, new_size); | |
257 } | |
258 | |
248 // Operations about the bottom left corner | 259 // Operations about the bottom left corner |
249 | 260 |
250 Rectangle expand(in Rectangle r, in Vector expand_amount) { | 261 Rectangle expand(in Rectangle r, in Vector expand_amount) { |
251 return Rectangle(r.position, r.size + expand_amount); | 262 return Rectangle(r.position, r.size + expand_amount); |
252 } | 263 } |
257 | 268 |
258 // Operations about the centre | 269 // Operations about the centre |
259 | 270 |
260 Rectangle feather(in Rectangle r, double amount) { | 271 Rectangle feather(in Rectangle r, double amount) { |
261 assert(amount >= 0.0); | 272 assert(amount >= 0.0); |
273 assert(!isnan(amount)); | |
262 return Rectangle(Point(r.position.x - amount, r.position.y - amount), | 274 return Rectangle(Point(r.position.x - amount, r.position.y - amount), |
263 Vector(r.size.x + 2.0 * amount, r.size.y + 2.0 * amount)); | 275 Vector(r.size.x + 2.0 * amount, r.size.y + 2.0 * amount)); |
264 } | 276 } |
265 | 277 |
266 Rectangle resize(in Rectangle r, in Vector new_size) { | |
267 return Rectangle(r.position, new_size); | |
268 } | |
269 | |
270 private { | 278 private { |
271 // This is a commmon building block for intersection of lines and segments | 279 // This function computes the intersection of two lines. |
272 // Two lines "a" and "b" are defined by two points each . | 280 // The lines are defined by a start point and an end point, however they |
273 // "ua" and "ub" define the intersection as a fraction along | 281 // notionally extend infinitely in each direction. |
274 // the two respective line segments (FIXME this comment sucks) | 282 // The out parameters specify the fraction along the line-segment at which |
283 // intersection occurred. | |
284 // | |
285 // This is a commmon building block for computing intersection between lines, segments, | |
286 // rectangles, etc. | |
287 // | |
288 // The function returns false if the lines are parallel or nearly so. | |
289 // | |
275 // Influenced by http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ | 290 // Influenced by http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ |
276 bool compute_intersection(in Point pa1, in Point pa2, out double ua, | 291 bool compute_intersection(in Point pa1, in Point pa2, out double ua, |
277 in Point pb1, in Point pb2, out double ub) { | 292 in Point pb1, in Point pb2, out double ub) { |
278 double den = (pb2.y - pb1.y) * (pa2.x - pa1.x) - (pb2.x - pb1.x) * (pa2.y - pa1.y); | 293 double den = (pb2.y - pb1.y) * (pa2.x - pa1.x) - (pb2.x - pb1.x) * (pa2.y - pa1.y); |
279 | 294 |
280 if (abs(den) < 1e-9) { // TODO consolidate constants used for numerical stability | 295 if (abs(den) < 1e-9) { // TODO consolidate constants used for numerical stability |
281 // Lines are parallel or nearly so | 296 // Lines are parallel or nearly so |
282 writefln("Warning, parallel lines!"); | 297 warning("Warning, parallel lines!"); |
283 return false; | 298 return false; |
284 } | 299 } |
285 else { | 300 else { |
286 // It will be safe to divide by den | 301 // It will be safe to divide by den |
287 double num_a = (pb2.x - pb1.x) * (pa1.y - pb1.y) - (pb2.y - pb1.y) * (pa1.x - pb1.x); | 302 double num_a = (pb2.x - pb1.x) * (pa1.y - pb1.y) - (pb2.y - pb1.y) * (pa1.x - pb1.x); |
291 ub = num_b / den; | 306 ub = num_b / den; |
292 | 307 |
293 return true; | 308 return true; |
294 } | 309 } |
295 } | 310 } |
311 | |
312 /+ | |
313 double compute_angle(in Point p1, in Point p2) { | |
314 } | |
315 +/ | |
296 } | 316 } |
297 | 317 |
298 // | 318 // |
299 // A line (notionally infinitely extending in both directions) in 2D space. | 319 // A line (notionally infinitely extending in both directions) in 2D space. |
300 // Internally represented by: | 320 // Internally represented by: |