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