92 lines
2.7 KiB
C
92 lines
2.7 KiB
C
/*
|
|
Fixed point implementation of 2 dimensional pnttors.
|
|
*/
|
|
|
|
#ifndef COM_PNT_H
|
|
#define COM_PNT_H
|
|
|
|
#include "def.h"
|
|
#include "fix.h"
|
|
#include "vec.h"
|
|
#include <stdint.h>
|
|
|
|
typedef struct {
|
|
com_def_alignedas(16) com_def_vector(com_fix_t, a, 2);
|
|
} com_pnt_t;
|
|
|
|
static inline com_pnt_t com_pnt_from(com_fix_t x, com_fix_t y) {
|
|
return (com_pnt_t){.a = {x, y}};
|
|
}
|
|
|
|
static inline com_pnt_t com_pnt_from_vec(com_vec_t a) {
|
|
return (com_pnt_t){.a = {a.a[0], a.a[1]}};
|
|
}
|
|
|
|
static inline com_pnt_t com_pnt_identity(void) {
|
|
return (com_pnt_t){.a = {
|
|
COM_FIX_FRACUNIT,
|
|
COM_FIX_FRACUNIT,
|
|
}};
|
|
}
|
|
|
|
static inline com_pnt_t com_pnt_add(com_pnt_t a, com_pnt_t b) {
|
|
return (com_pnt_t){
|
|
.a = {com_fix_add(a.a[0], b.a[0]), com_fix_add(a.a[1], b.a[1])}};
|
|
}
|
|
|
|
static inline com_pnt_t com_pnt_sub(com_pnt_t a, com_pnt_t b) {
|
|
return (com_pnt_t){
|
|
.a = {com_fix_sub(a.a[0], b.a[0]), com_fix_sub(a.a[1], b.a[1])}};
|
|
}
|
|
|
|
static inline com_pnt_t com_pnt_mul(com_pnt_t a, com_pnt_t b) {
|
|
return (com_pnt_t){
|
|
.a = {com_fix_mul(a.a[0], b.a[0]), com_fix_mul(a.a[1], b.a[1])}};
|
|
}
|
|
|
|
/* Note: this does not clamp for over/underflow cases */
|
|
static inline com_pnt_t com_pnt_div(com_pnt_t a, com_pnt_t b) {
|
|
return (com_pnt_t){
|
|
.a = {com_fix_div(a.a[0], b.a[0]), com_fix_div(a.a[1], b.a[1])}};
|
|
}
|
|
|
|
/* Scale pnttor by a fixed point number */
|
|
static inline com_pnt_t com_pnt_scl(com_pnt_t a, com_fix_t b) {
|
|
return (com_pnt_t){.a = {com_fix_mul(a.a[0], b), com_fix_mul(a.a[1], b)}};
|
|
}
|
|
|
|
static inline com_fix_t com_pnt_min(com_pnt_t a) {
|
|
return com_fix_min(a.a[0], a.a[1]);
|
|
}
|
|
|
|
static inline com_fix_t com_pnt_max(com_pnt_t a) {
|
|
return com_fix_max(a.a[0], a.a[1]);
|
|
}
|
|
|
|
/* TODO: Safeguard by com_fix_mul()? */
|
|
/* Tests whether a point is lying right to a line produced by l0 and l1.
|
|
This assumes that l0 and l1 are in clockwise order.
|
|
Result is positive or zero if it holds true, otherwise it's negative.
|
|
This also produces area of a triangle! */
|
|
static inline com_fix_t com_pnt_edge_orient(com_pnt_t l0, com_pnt_t l1,
|
|
com_pnt_t p) {
|
|
return (l0.a[0] - l1.a[0]) * (p.a[1] - l1.a[1]) -
|
|
(l0.a[1] - l1.a[1]) * (p.a[0] - l1.a[0]);
|
|
}
|
|
|
|
#define com_pnt_area(m_p0, m_p1, m_p2) (com_pnt_edge_orient(m_p0, m_p1, m_p2))
|
|
|
|
static inline com_vec_t com_pnt_edge_weight(com_pnt_t v0, com_pnt_t v1,
|
|
com_pnt_t v2, com_pnt_t p) {
|
|
return (com_vec_t){.a = {com_pnt_edge_orient(v1, v2, p),
|
|
com_pnt_edge_orient(v2, v0, p),
|
|
com_pnt_edge_orient(v0, v1, p)}};
|
|
}
|
|
|
|
static inline void com_pnt_print(com_pnt_t a) {
|
|
com_fix_print(a.a[0]);
|
|
com_fix_print(a.a[1]);
|
|
}
|
|
|
|
#endif
|