1 /**
2 * @file point.c
3 * 2D points.
4 *
5 * @authors Copyright © 2013 Daniel Swanson <danij@dengine.net>
6 *
7 * @par License
8 * GPL: http://www.gnu.org/licenses/gpl.html
9 *
10 * <small>This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version. This program is distributed in the hope that it
14 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details. You should have received a copy of the GNU
17 * General Public License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19 * 02110-1301 USA</small>
20 */
21
22 #include "de/point.h"
23 #include "de/memory.h"
24
25 struct point2_s {
26 /// Use a "raw" Point natively so that we can simply copy when called upon.
27 Point2Raw raw;
28 };
29
30 struct point2f_s {
31 /// Use a "raw" Point natively so that we can simply copy when called upon.
32 Point2Rawf raw;
33 };
34
Point2_New(void)35 Point2 *Point2_New(void)
36 {
37 Point2 *p = M_Calloc(sizeof *p);
38 return p;
39 }
40
Point2_NewWithCoords(int x,int y)41 Point2 *Point2_NewWithCoords(int x, int y)
42 {
43 Point2 *p = Point2_New();
44 Point2_SetXY(p, x, y);
45 return p;
46 }
47
Point2_NewFromRaw(Point2Raw const * rawPoint)48 Point2 *Point2_NewFromRaw(Point2Raw const *rawPoint)
49 {
50 DENG_ASSERT(rawPoint);
51 return Point2_NewWithCoords(rawPoint->x, rawPoint->y);
52 }
53
Point2_Delete(Point2 * p)54 void Point2_Delete(Point2 *p)
55 {
56 DENG_ASSERT(p);
57 M_Free(p);
58 }
59
Point2_IsNull(Point2 const * p)60 dd_bool Point2_IsNull(Point2 const *p)
61 {
62 DENG_ASSERT(p);
63 return p->raw.x == 0 && p->raw.y == 0;
64 }
65
Point2_Raw(Point2 const * p,Point2Raw * rawPoint)66 Point2Raw *Point2_Raw(Point2 const *p, Point2Raw *rawPoint)
67 {
68 DENG_ASSERT(p);
69 if (!rawPoint) return NULL;
70 memcpy(rawPoint, &p->raw, sizeof(*rawPoint));
71 return rawPoint;
72 }
73
Point2_X(Point2 const * p)74 int Point2_X(Point2 const *p)
75 {
76 DENG_ASSERT(p);
77 return p->raw.x;
78 }
79
Point2_Y(Point2 const * p)80 int Point2_Y(Point2 const *p)
81 {
82 DENG_ASSERT(p);
83 return p->raw.y;
84 }
85
Point2_SetX(Point2 * p,int x)86 void Point2_SetX(Point2 *p, int x)
87 {
88 DENG_ASSERT(p);
89 p->raw.x = x;
90 }
91
Point2_SetY(Point2 * p,int y)92 void Point2_SetY(Point2 *p, int y)
93 {
94 DENG_ASSERT(p);
95 p->raw.y = y;
96 }
97
Point2_XY(Point2 const * p)98 int const *Point2_XY(Point2 const *p)
99 {
100 DENG_ASSERT(p);
101 return p->raw.xy;
102 }
103
Point2_SetXY(Point2 * p,int x,int y)104 void Point2_SetXY(Point2 *p, int x, int y)
105 {
106 DENG_ASSERT(p);
107 p->raw.x = x;
108 p->raw.y = y;
109 }
110
Point2_Translate(Point2 * p,Point2Raw const * delta)111 void Point2_Translate(Point2 *p, Point2Raw const *delta)
112 {
113 DENG_ASSERT(p);
114 if (!delta) return;
115 p->raw.x += delta->x;
116 p->raw.y += delta->y;
117 }
118
Point2_TranslateXY(Point2 * p,int x,int y)119 void Point2_TranslateXY(Point2 *p, int x, int y)
120 {
121 DENG_ASSERT(p);
122 p->raw.x += x;
123 p->raw.y += y;
124 }
125
Point2_TranslateX(Point2 * p,int x)126 void Point2_TranslateX(Point2 *p, int x)
127 {
128 DENG_ASSERT(p);
129 p->raw.x += x;
130 }
131
Point2_TranslateY(Point2 * p,int y)132 void Point2_TranslateY(Point2 *p, int y)
133 {
134 DENG_ASSERT(p);
135 p->raw.y += y;
136 }
137
Point2_Sum(Point2 * p,Point2 const * other)138 void Point2_Sum(Point2 *p, Point2 const *other)
139 {
140 DENG_ASSERT(p && other);
141 p->raw.x += Point2_X(other);
142 p->raw.y += Point2_Y(other);
143 }
144
Point2_Equality(Point2 const * p,Point2 const * other)145 dd_bool Point2_Equality(Point2 const *p, Point2 const *other)
146 {
147 DENG_ASSERT(p && other);
148 return p == other || (p->raw.x == Point2_X(other) && p->raw.y == Point2_Y(other));
149 }
150
Point2f_New(void)151 Point2f *Point2f_New(void)
152 {
153 Point2f *p = M_Calloc(sizeof *p);
154 return p;
155 }
156
Point2f_NewWithCoords(double x,double y)157 Point2f *Point2f_NewWithCoords(double x, double y)
158 {
159 Point2f *p = Point2f_New();
160 Point2f_SetXY(p, x, y);
161 return p;
162 }
163
Point2f_NewFromRaw(Point2Rawf const * rawPoint)164 Point2f *Point2f_NewFromRaw(Point2Rawf const *rawPoint)
165 {
166 DENG_ASSERT(rawPoint);
167 return Point2f_NewWithCoords(rawPoint->x, rawPoint->y);
168 }
169
Point2f_Delete(Point2f * p)170 void Point2f_Delete(Point2f *p)
171 {
172 DENG_ASSERT(p);
173 M_Free(p);
174 }
175
Point2f_IsNull(Point2f const * p)176 dd_bool Point2f_IsNull(Point2f const *p)
177 {
178 DENG_ASSERT(p);
179 return p->raw.x == 0 && p->raw.y == 0;
180 }
181
Point2f_Raw(Point2f const * p,Point2Rawf * rawPoint)182 Point2Rawf *Point2f_Raw(Point2f const *p, Point2Rawf *rawPoint)
183 {
184 DENG_ASSERT(p);
185 if (!rawPoint) return NULL;
186 memcpy(rawPoint, &p->raw, sizeof(*rawPoint));
187 return rawPoint;
188 }
189
Point2f_X(Point2f const * p)190 double Point2f_X(Point2f const *p)
191 {
192 DENG_ASSERT(p);
193 return p->raw.x;
194 }
195
Point2f_Y(Point2f const * p)196 double Point2f_Y(Point2f const *p)
197 {
198 DENG_ASSERT(p);
199 return p->raw.y;
200 }
201
Point2f_SetX(Point2f * p,double x)202 void Point2f_SetX(Point2f *p, double x)
203 {
204 DENG_ASSERT(p);
205 p->raw.x = x;
206 }
207
Point2f_SetY(Point2f * p,double y)208 void Point2f_SetY(Point2f *p, double y)
209 {
210 DENG_ASSERT(p);
211 p->raw.y = y;
212 }
213
Point2f_XY(Point2f const * p)214 double const *Point2f_XY(Point2f const *p)
215 {
216 DENG_ASSERT(p);
217 return p->raw.xy;
218 }
219
Point2f_SetXY(Point2f * p,double x,double y)220 void Point2f_SetXY(Point2f *p, double x, double y)
221 {
222 DENG_ASSERT(p);
223 p->raw.x = x;
224 p->raw.y = y;
225 }
226
Point2f_Translate(Point2f * p,Point2Rawf const * delta)227 void Point2f_Translate(Point2f *p, Point2Rawf const *delta)
228 {
229 DENG_ASSERT(p);
230 if (!delta) return;
231 p->raw.x += delta->x;
232 p->raw.y += delta->y;
233 }
234
Point2f_TranslateXY(Point2f * p,double x,double y)235 void Point2f_TranslateXY(Point2f *p, double x, double y)
236 {
237 DENG_ASSERT(p);
238 p->raw.x += x;
239 p->raw.y += y;
240 }
241
Point2f_TranslateX(Point2f * p,double x)242 void Point2f_TranslateX(Point2f *p, double x)
243 {
244 DENG_ASSERT(p);
245 p->raw.x += x;
246 }
247
Point2f_TranslateY(Point2f * p,double y)248 void Point2f_TranslateY(Point2f *p, double y)
249 {
250 DENG_ASSERT(p);
251 p->raw.y += y;
252 }
253
Point2f_Sum(Point2f * p,Point2f const * other)254 void Point2f_Sum(Point2f *p, Point2f const *other)
255 {
256 DENG_ASSERT(p && other);
257 p->raw.x += Point2f_X(other);
258 p->raw.y += Point2f_Y(other);
259 }
260
Point2f_Equality(Point2f const * p,Point2f const * other)261 dd_bool Point2f_Equality(Point2f const *p, Point2f const *other)
262 {
263 DENG_ASSERT(p && other);
264 return p == other || (p->raw.x == Point2f_X(other) && p->raw.y == Point2f_Y(other));
265 }
266
267 struct point3_s {
268 /// Use a "raw" Point natively so that we can simply copy when called upon.
269 Point3Raw raw;
270 };
271
272 struct point3f_s {
273 /// Use a "raw" Point natively so that we can simply copy when called upon.
274 Point3Rawf raw;
275 };
276
Point3_New(void)277 Point3 *Point3_New(void)
278 {
279 Point3 *p = M_Calloc(sizeof *p);
280 return p;
281 }
282
Point3_NewWithCoords(int x,int y,int z)283 Point3 *Point3_NewWithCoords(int x, int y, int z)
284 {
285 Point3 *p = Point3_New();
286 Point3_SetXYZ(p, x, y, z);
287 return p;
288 }
289
Point3_NewFromRaw(Point3Raw const * rawPoint)290 Point3 *Point3_NewFromRaw(Point3Raw const *rawPoint)
291 {
292 DENG_ASSERT(rawPoint);
293 return Point3_NewWithCoords(rawPoint->x, rawPoint->y, rawPoint->z);
294 }
295
Point3_Delete(Point3 * p)296 void Point3_Delete(Point3 *p)
297 {
298 DENG_ASSERT(p);
299 M_Free(p);
300 }
301
Point3_IsNull(Point3 const * p)302 dd_bool Point3_IsNull(Point3 const *p)
303 {
304 DENG_ASSERT(p);
305 return p->raw.x == 0 && p->raw.y == 0 && p->raw.z == 0;
306 }
307
Point3_Raw(Point3 const * p,Point3Raw * rawPoint)308 Point3Raw *Point3_Raw(Point3 const *p, Point3Raw *rawPoint)
309 {
310 DENG_ASSERT(p);
311 if (!rawPoint) return NULL;
312 memcpy(rawPoint, &p->raw, sizeof(*rawPoint));
313 return rawPoint;
314 }
315
Point3_X(Point3 const * p)316 int Point3_X(Point3 const *p)
317 {
318 DENG_ASSERT(p);
319 return p->raw.x;
320 }
321
Point3_Y(Point3 const * p)322 int Point3_Y(Point3 const *p)
323 {
324 DENG_ASSERT(p);
325 return p->raw.y;
326 }
327
Point3_Z(Point3 const * p)328 int Point3_Z(Point3 const *p)
329 {
330 DENG_ASSERT(p);
331 return p->raw.z;
332 }
333
Point3_SetX(Point3 * p,int x)334 void Point3_SetX(Point3 *p, int x)
335 {
336 DENG_ASSERT(p);
337 p->raw.x = x;
338 }
339
Point3_SetY(Point3 * p,int y)340 void Point3_SetY(Point3 *p, int y)
341 {
342 DENG_ASSERT(p);
343 p->raw.y = y;
344 }
345
Point3_SetZ(Point3 * p,int z)346 void Point3_SetZ(Point3 *p, int z)
347 {
348 DENG_ASSERT(p);
349 p->raw.z = z;
350 }
351
Point3_XYZ(Point3 const * p)352 int const *Point3_XYZ(Point3 const *p)
353 {
354 DENG_ASSERT(p);
355 return p->raw.xyz;
356 }
357
Point3_SetXYZ(Point3 * p,int x,int y,int z)358 void Point3_SetXYZ(Point3 *p, int x, int y, int z)
359 {
360 DENG_ASSERT(p);
361 p->raw.x = x;
362 p->raw.y = y;
363 p->raw.z = z;
364 }
365
Point3_Translate(Point3 * p,int x,int y,int z)366 void Point3_Translate(Point3 *p, int x, int y, int z)
367 {
368 DENG_ASSERT(p);
369 p->raw.x += x;
370 p->raw.y += y;
371 p->raw.z += z;
372 }
373
Point3_TranslateX(Point3 * p,int x)374 void Point3_TranslateX(Point3 *p, int x)
375 {
376 DENG_ASSERT(p);
377 p->raw.x += x;
378 }
379
Point3_TranslateY(Point3 * p,int y)380 void Point3_TranslateY(Point3 *p, int y)
381 {
382 DENG_ASSERT(p);
383 p->raw.y += y;
384 }
385
Point3_TranslateZ(Point3 * p,int z)386 void Point3_TranslateZ(Point3 *p, int z)
387 {
388 DENG_ASSERT(p);
389 p->raw.z += z;
390 }
391
Point3_Sum(Point3 * p,Point3 const * other)392 void Point3_Sum(Point3 *p, Point3 const *other)
393 {
394 DENG_ASSERT(p && other);
395 p->raw.x += Point3_X(other);
396 p->raw.y += Point3_Y(other);
397 p->raw.z += Point3_Z(other);
398 }
399
Point3_Equality(Point3 const * p,Point3 const * other)400 dd_bool Point3_Equality(Point3 const *p, Point3 const *other)
401 {
402 DENG_ASSERT(p && other);
403 return p == other || (p->raw.x == Point3_X(other) &&
404 p->raw.y == Point3_Y(other) &&
405 p->raw.z == Point3_Z(other));
406 }
407
Point3f_New(void)408 Point3f *Point3f_New(void)
409 {
410 Point3f *p = M_Calloc(sizeof *p);
411 return p;
412 }
413
Point3f_NewWithCoords(double x,double y,double z)414 Point3f *Point3f_NewWithCoords(double x, double y, double z)
415 {
416 Point3f *p = Point3f_New();
417 Point3f_SetXYZ(p, x, y, z);
418 return p;
419 }
420
Point3f_NewFromRaw(Point3Rawf const * rawPoint)421 Point3f *Point3f_NewFromRaw(Point3Rawf const *rawPoint)
422 {
423 DENG_ASSERT(rawPoint);
424 return Point3f_NewWithCoords(rawPoint->x, rawPoint->y, rawPoint->z);
425 }
426
Point3f_Delete(Point3f * p)427 void Point3f_Delete(Point3f *p)
428 {
429 DENG_ASSERT(p);
430 M_Free(p);
431 }
432
Point3f_IsNull(Point3f const * p)433 dd_bool Point3f_IsNull(Point3f const *p)
434 {
435 DENG_ASSERT(p);
436 return p->raw.x == 0 && p->raw.y == 0 && p->raw.z == 0;
437 }
438
Point3f_Raw(Point3f const * p,Point3Rawf * rawPoint)439 Point3Rawf *Point3f_Raw(Point3f const *p, Point3Rawf *rawPoint)
440 {
441 DENG_ASSERT(p);
442 if (!rawPoint) return NULL;
443 memcpy(rawPoint, &p->raw, sizeof(*rawPoint));
444 return rawPoint;
445 }
446
Point3f_X(Point3f const * p)447 double Point3f_X(Point3f const *p)
448 {
449 DENG_ASSERT(p);
450 return p->raw.x;
451 }
452
Point3f_Y(Point3f const * p)453 double Point3f_Y(Point3f const *p)
454 {
455 DENG_ASSERT(p);
456 return p->raw.y;
457 }
458
Point3f_Z(Point3f const * p)459 double Point3f_Z(Point3f const *p)
460 {
461 DENG_ASSERT(p);
462 return p->raw.z;
463 }
464
Point3f_SetX(Point3f * p,double x)465 void Point3f_SetX(Point3f *p, double x)
466 {
467 DENG_ASSERT(p);
468 p->raw.x = x;
469 }
470
Point3f_SetY(Point3f * p,double y)471 void Point3f_SetY(Point3f *p, double y)
472 {
473 DENG_ASSERT(p);
474 p->raw.y = y;
475 }
476
Point3f_SetZ(Point3f * p,double z)477 void Point3f_SetZ(Point3f *p, double z)
478 {
479 DENG_ASSERT(p);
480 p->raw.z = z;
481 }
482
Point3f_XYZ(Point3f const * p)483 double const *Point3f_XYZ(Point3f const *p)
484 {
485 DENG_ASSERT(p);
486 return p->raw.xyz;
487 }
488
Point3f_SetXYZ(Point3f * p,double x,double y,double z)489 void Point3f_SetXYZ(Point3f *p, double x, double y, double z)
490 {
491 DENG_ASSERT(p);
492 p->raw.x = x;
493 p->raw.y = y;
494 p->raw.z = z;
495 }
496
Point3f_Translate(Point3f * p,double x,double y,double z)497 void Point3f_Translate(Point3f *p, double x, double y, double z)
498 {
499 DENG_ASSERT(p);
500 p->raw.x += x;
501 p->raw.y += y;
502 p->raw.z += z;
503 }
504
Point3f_TranslateX(Point3f * p,double x)505 void Point3f_TranslateX(Point3f *p, double x)
506 {
507 DENG_ASSERT(p);
508 p->raw.x += x;
509 }
510
Point3f_TranslateY(Point3f * p,double y)511 void Point3f_TranslateY(Point3f *p, double y)
512 {
513 DENG_ASSERT(p);
514 p->raw.y += y;
515 }
516
Point3f_TranslateZ(Point3f * p,double z)517 void Point3f_TranslateZ(Point3f *p, double z)
518 {
519 DENG_ASSERT(p);
520 p->raw.z += z;
521 }
522
Point3f_Sum(Point3f * p,Point3f const * other)523 void Point3f_Sum(Point3f *p, Point3f const *other)
524 {
525 DENG_ASSERT(p && other);
526 p->raw.x += Point3f_X(other);
527 p->raw.y += Point3f_Y(other);
528 p->raw.z += Point3f_Z(other);
529 }
530
Point3f_Equality(Point3f const * p,Point3f const * other)531 dd_bool Point3f_Equality(Point3f const *p, Point3f const *other)
532 {
533 DENG_ASSERT(p && other);
534 return p == other || (p->raw.x == Point3f_X(other) &&
535 p->raw.y == Point3f_Y(other) &&
536 p->raw.z == Point3f_Z(other));
537 }
538