1 //------------------------------------------------------------------------
2 // EPI Vector (point) types
3 //------------------------------------------------------------------------
4 //
5 // Copyright (c) 2004-2008 The EDGE Team.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 //------------------------------------------------------------------------
18
19 #ifndef __EPI_MATH_VECTOR__
20 #define __EPI_MATH_VECTOR__
21
22 #include "macros.h"
23 #include "math_angle.h"
24
25 namespace epi
26 {
27
28 class ivec_c
29 {
30 /* sealed class, value semantics */
31
32 public:
33 int x, y;
34
ivec_c()35 ivec_c() : x(0), y(0) { }
ivec_c(int nx,int ny)36 ivec_c(int nx, int ny) : x(nx), y(ny) { }
ivec_c(const ivec_c & rhs)37 ivec_c(const ivec_c& rhs) : x(rhs.x), y(rhs.y) { }
38
39 /* ---- read-only operations ---- */
40
41 float Length() const;
42 int ApproxLength() const;
43
44 bool operator==(const ivec_c& rhs) const;
45 bool operator!=(const ivec_c& rhs) const;
46
47 ivec_c operator- ();
48
49 ivec_c operator+ (const ivec_c& rhs) const;
50 ivec_c operator- (const ivec_c& rhs) const;
51 ivec_c operator* (int scale) const;
52 ivec_c operator/ (int scale) const;
53
54 int operator* (const ivec_c& rhs) const; // dot product
55
56 /* ---- modifying operations ---- */
57
58 ivec_c& Rotate90(); //
59 ivec_c& Rotate180(); // anti-clockwise
60 ivec_c& Rotate270(); //
61
62 ivec_c& operator= (const ivec_c& rhs);
63
64 ivec_c& operator+= (const ivec_c& rhs);
65 ivec_c& operator-= (const ivec_c& rhs);
66 ivec_c& operator*= (int scale);
67 ivec_c& operator/= (int scale);
68 };
69
70 class vec2_c
71 {
72 /* sealed class, value semantics */
73
74 public:
75 float x, y;
76
vec2_c()77 vec2_c() : x(0), y(0) { }
vec2_c(float nx,float ny)78 vec2_c(float nx, float ny) : x(nx), y(ny) { }
vec2_c(const vec2_c & rhs)79 vec2_c(const vec2_c& rhs) : x(rhs.x), y(rhs.y) { }
vec2_c(const ivec_c & rhs)80 vec2_c(const ivec_c& rhs) : x(rhs.x), y(rhs.y) { }
vec2_c(const angle_c & ang)81 vec2_c(const angle_c& ang) : x(ang.getX()), y(ang.getY()) { }
vec2_c(const angle_c & ang,float len)82 vec2_c(const angle_c& ang, float len)
83 : x(ang.getX() * len), y(ang.getY() * len) { }
84
85 /* ---- read-only operations ---- */
86
87 float Length() const;
88 float ApproxLength() const;
89
90 bool onRight(const vec2_c& point) const;
91 // returns true if point is on the RIGHT side of this vector,
92 // false if on the LEFT side. Undefined if directly on the line.
93
94 float PerpDist(const vec2_c& point) const;
95 // return perpendicular distance from this vector (extended to
96 // infinity) to the given point. Result is positive on the
97 // right side, negative on the left.
98
99 float AlongDist(const vec2_c& point) const;
100 // return parallel distance from (0,0) to the point on the vector
101 // (extended to infinity) which is closest to the given point.
102
103 bool Match(const vec2_c& rhs, float precision = 0.001f);
104 // no equality operators since we're using floating point.
105
106 vec2_c operator- ();
107
108 vec2_c operator+ (const vec2_c& rhs) const;
109 vec2_c operator- (const vec2_c& rhs) const;
110 vec2_c operator* (float scale) const;
111 vec2_c operator/ (float scale) const;
112
113 float operator* (const vec2_c& rhs) const; // dot product
114
115 /* ---- modifying operations ---- */
116
117 vec2_c& MakeUnit(); // make unit length
118
119 vec2_c& Rotate(const angle_c& ang); // anti-clockwise
120
121 vec2_c& Rotate90(); //
122 vec2_c& Rotate180(); // anti-clockwise
123 vec2_c& Rotate270(); //
124
125 vec2_c& operator= (const vec2_c& rhs);
126
127 vec2_c& operator+= (const vec2_c& rhs);
128 vec2_c& operator-= (const vec2_c& rhs);
129 vec2_c& operator*= (float scale);
130 vec2_c& operator/= (float scale);
131 };
132
133 class vec3_c
134 {
135 /* sealed class, value semantics */
136
137 public:
138 float x, y, z;
139
vec3_c()140 vec3_c() : x(0), y(0), z(0) { }
vec3_c(float nx,float ny,float nz)141 vec3_c(float nx, float ny, float nz) : x(nx), y(ny), z(nz) { }
vec3_c(const vec3_c & rhs)142 vec3_c(const vec3_c& rhs) : x(rhs.x), y(rhs.y), z(rhs.z) { }
vec3_c(const vec2_c & horiz,float nz)143 vec3_c(const vec2_c& horiz, float nz) : x(horiz.x), y(horiz.y), z(nz) { }
144
145 /* ---- read-only operations ---- */
146
147 float Length() const;
148 float Slope() const;
149
150 float ApproxLength() const;
151 float ApproxSlope() const;
152
153 float AlongDist(const vec3_c& point) const;
154 // return parallel distance from (0,0,0) to the point on the vector
155 // (extended to infinity) which is closest to the given point.
156
157 bool Match(const vec3_c& rhs, float precision = 0.001f);
158 // no equality operators since we're using floating point.
159
160 vec2_c Get2D() const;
161 // return the 2D vector (dropping the z coord).
162
163 vec3_c operator- ();
164
165 vec3_c operator+ (const vec3_c& rhs) const;
166 vec3_c operator- (const vec3_c& rhs) const;
167 vec3_c operator* (float scale) const;
168 vec3_c operator/ (float scale) const;
169
170 float operator* (const vec3_c& rhs) const; // dot product
171
172 vec3_c Cross(const vec3_c& rhs) const; // cross product
173
174 /* ---- modifying operations ---- */
175
176 vec3_c& MakeUnit(); // make unit length
177
178 vec3_c& operator= (const vec3_c& rhs);
179
180 vec3_c& operator+= (const vec3_c& rhs);
181 vec3_c& operator-= (const vec3_c& rhs);
182 vec3_c& operator*= (float scale);
183 vec3_c& operator/= (float scale);
184 };
185
186 //------------------------------------------------------------------------
187 // IMPLEMENTATION
188 //------------------------------------------------------------------------
189
ApproxLength()190 inline int ivec_c::ApproxLength() const
191 {
192 int ax = ABS(x);
193 int ay = ABS(y);
194
195 return (ax > ay) ? (ax + ay / 2) : (ay + ax / 2);
196 }
197
198 inline bool ivec_c::operator==(const ivec_c& rhs) const
199 {
200 return (rhs.x == x) && (rhs.y == y);
201 }
202
203 inline bool ivec_c::operator!=(const ivec_c& rhs) const
204 {
205 return (rhs.x != x) || (rhs.y != y);
206 }
207
208 inline ivec_c ivec_c::operator- ()
209 {
210 return ivec_c(-x, -y);
211 }
212
213 inline ivec_c ivec_c::operator+ (const ivec_c& rhs) const
214 {
215 return ivec_c(x + rhs.x, y + rhs.y);
216 }
217
218 inline ivec_c ivec_c::operator- (const ivec_c& rhs) const
219 {
220 return ivec_c(x - rhs.x, y - rhs.y);
221 }
222
223 inline ivec_c ivec_c::operator* (int scale) const
224 {
225 return ivec_c(x * scale, y * scale);
226 }
227
228 inline ivec_c ivec_c::operator/ (int scale) const
229 {
230 return ivec_c(x / scale, y / scale);
231 }
232
233 inline int ivec_c::operator* (const ivec_c& rhs) const
234 {
235 return x * rhs.x + y * rhs.y;
236 }
237
238 inline ivec_c& ivec_c::operator= (const ivec_c& rhs)
239 {
240 x = rhs.x; y = rhs.y;
241 return *this;
242 }
243
244 inline ivec_c& ivec_c::operator+= (const ivec_c& rhs)
245 {
246 x += rhs.x; y += rhs.y;
247 return *this;
248 }
249
250 inline ivec_c& ivec_c::operator-= (const ivec_c& rhs)
251 {
252 x -= rhs.x; y -= rhs.y;
253 return *this;
254 }
255
256 inline ivec_c& ivec_c::operator*= (int scale)
257 {
258 x *= scale; y *= scale;
259 return *this;
260 }
261
262 inline ivec_c& ivec_c::operator/= (int scale)
263 {
264 x /= scale; y /= scale;
265 return *this;
266 }
267
Rotate90()268 inline ivec_c& ivec_c::Rotate90()
269 {
270 int tmp = y; y = x; x = -tmp;
271 return *this;
272 }
273
Rotate180()274 inline ivec_c& ivec_c::Rotate180()
275 {
276 x = -x; y = -y;
277 return *this;
278 }
279
Rotate270()280 inline ivec_c& ivec_c::Rotate270()
281 {
282 int tmp = x; x = y; y = -tmp;
283 return *this;
284 }
285
286
287 //------------------------------------------------------------------------
288
ApproxLength()289 inline float vec2_c::ApproxLength() const
290 {
291 float ax = ABS(x);
292 float ay = ABS(y);
293
294 return (ax > ay) ? (ax + ay / 2) : (ay + ax / 2);
295 }
296
onRight(const vec2_c & point)297 inline bool vec2_c::onRight(const vec2_c& point) const
298 {
299 return (point.x * y >= point.y * x);
300 }
301
Match(const vec2_c & rhs,float precision)302 inline bool vec2_c::Match(const vec2_c& rhs, float precision)
303 {
304 return fabs(x - rhs.x) < precision && fabs(y - rhs.y) < precision;
305 }
306
307 inline vec2_c vec2_c::operator- ()
308 {
309 return vec2_c(-x, -y);
310 }
311
312 inline vec2_c vec2_c::operator+ (const vec2_c& rhs) const
313 {
314 return vec2_c(x + rhs.x, y + rhs.y);
315 }
316
317 inline vec2_c vec2_c::operator- (const vec2_c& rhs) const
318 {
319 return vec2_c(x - rhs.x, y - rhs.y);
320 }
321
322 inline vec2_c vec2_c::operator* (float scale) const
323 {
324 return vec2_c(x * scale, y * scale);
325 }
326
327 inline vec2_c vec2_c::operator/ (float scale) const
328 {
329 return vec2_c(x / scale, y / scale);
330 }
331
332 inline float vec2_c::operator* (const vec2_c& rhs) const
333 {
334 return x * rhs.x + y * rhs.y;
335 }
336
MakeUnit()337 inline vec2_c& vec2_c::MakeUnit()
338 {
339 *this /= Length();
340 return *this;
341 }
342
343 inline vec2_c& vec2_c::operator= (const vec2_c& rhs)
344 {
345 x = rhs.x; y = rhs.y;
346 return *this;
347 }
348
349 inline vec2_c& vec2_c::operator+= (const vec2_c& rhs)
350 {
351 x += rhs.x; y += rhs.y;
352 return *this;
353 }
354
355 inline vec2_c& vec2_c::operator-= (const vec2_c& rhs)
356 {
357 x -= rhs.x; y -= rhs.y;
358 return *this;
359 }
360
361 inline vec2_c& vec2_c::operator*= (float scale)
362 {
363 x *= scale; y *= scale;
364 return *this;
365 }
366
367 inline vec2_c& vec2_c::operator/= (float scale)
368 {
369 x /= scale; y /= scale;
370 return *this;
371 }
372
Rotate(const angle_c & ang)373 inline vec2_c& vec2_c::Rotate(const angle_c& ang)
374 {
375 float s = ang.Sin();
376 float c = ang.Cos();
377
378 float ox = x;
379 float oy = y;
380
381 x = ox * c - oy * s;
382 y = oy * c + ox * s;
383
384 return *this;
385 }
386
Rotate90()387 inline vec2_c& vec2_c::Rotate90()
388 {
389 float tmp = y; y = x; x = -tmp;
390 return *this;
391 }
392
Rotate180()393 inline vec2_c& vec2_c::Rotate180()
394 {
395 x = -x; y = -y;
396 return *this;
397 }
398
Rotate270()399 inline vec2_c& vec2_c::Rotate270()
400 {
401 float tmp = x; x = y; y = -tmp;
402 return *this;
403 }
404
405
406 //------------------------------------------------------------------------
407
ApproxLength()408 inline float vec3_c::ApproxLength() const
409 {
410 float ax = ABS(x);
411 float ay = ABS(y);
412 float az = ABS(z);
413
414 float axy = (ax > ay) ? (ax + ay / 2) : (ay + ax / 2);
415
416 return (axy > az) ? (axy + az / 2) : (az + axy / 2);
417 }
418
Match(const vec3_c & rhs,float precision)419 inline bool vec3_c::Match(const vec3_c& rhs, float precision)
420 {
421 return fabs(x - rhs.x) < precision &&
422 fabs(y - rhs.y) < precision &&
423 fabs(z - rhs.z) < precision;
424 }
425
Get2D()426 inline vec2_c vec3_c::Get2D() const
427 {
428 return vec2_c(x, y);
429 }
430
431 inline vec3_c vec3_c::operator- ()
432 {
433 return vec3_c(-x, -y, -z);
434 }
435
436 inline vec3_c vec3_c::operator+ (const vec3_c& rhs) const
437 {
438 return vec3_c(x + rhs.x, y + rhs.y, z + rhs.z);
439 }
440
441 inline vec3_c vec3_c::operator- (const vec3_c& rhs) const
442 {
443 return vec3_c(x - rhs.x, y - rhs.y, z - rhs.z);
444 }
445
446 inline vec3_c vec3_c::operator* (float scale) const
447 {
448 return vec3_c(x * scale, y * scale, z * scale);
449 }
450
451 inline vec3_c vec3_c::operator/ (float scale) const
452 {
453 return vec3_c(x / scale, y / scale, z / scale);
454 }
455
456 inline float vec3_c::operator* (const vec3_c& rhs) const
457 {
458 return x * rhs.x + y * rhs.y + z * rhs.z;
459 }
460
MakeUnit()461 inline vec3_c& vec3_c::MakeUnit()
462 {
463 *this /= Length();
464 return *this;
465 }
466
467 inline vec3_c& vec3_c::operator= (const vec3_c& rhs)
468 {
469 x = rhs.x; y = rhs.y; z = rhs.z;
470 return *this;
471 }
472
473 inline vec3_c& vec3_c::operator+= (const vec3_c& rhs)
474 {
475 x += rhs.x; y += rhs.y; z += rhs.z;
476 return *this;
477 }
478
479 inline vec3_c& vec3_c::operator-= (const vec3_c& rhs)
480 {
481 x -= rhs.x; y -= rhs.y; z -= rhs.z;
482 return *this;
483 }
484
485 inline vec3_c& vec3_c::operator*= (float scale)
486 {
487 x *= scale; y *= scale; z *= scale;
488 return *this;
489 }
490
491 inline vec3_c& vec3_c::operator/= (float scale)
492 {
493 x /= scale; y /= scale; z /= scale;
494 return *this;
495 }
496
497 } // namespace epi
498
499 #endif /* __EPI_MATH_VECTOR__ */
500
501 //--- editor settings ---
502 // vi:ts=4:sw=4:noexpandtab
503