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