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: