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 }