summaryrefslogtreecommitdiffstats
path: root/libdimension/dimension/geometry.h
diff options
context:
space:
mode:
Diffstat (limited to 'libdimension/dimension/geometry.h')
-rw-r--r--libdimension/dimension/geometry.h194
1 files changed, 108 insertions, 86 deletions
diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h
index fd4a781..7b52a98 100644
--- a/libdimension/dimension/geometry.h
+++ b/libdimension/dimension/geometry.h
@@ -26,105 +26,115 @@
#include <math.h>
#include <stdbool.h>
-/// A vector in 3 dimensions.
+/** A vector in 3 dimensions. */
typedef struct dmnsn_vector {
- double x; ///< The x component.
- double y; ///< The y component.
- double z; ///< The z component.
+ double x; /**< The x component. */
+ double y; /**< The y component. */
+ double z; /**< The z component. */
} dmnsn_vector;
-/// A standard format string for vectors.
+/** A standard format string for vectors. */
#define DMNSN_VECTOR_FORMAT "<%g, %g, %g>"
-/// The appropriate arguements to printf() a vector.
+/** The appropriate arguements to printf() a vector. */
#define DMNSN_VECTOR_PRINTF(v) (v).x, (v).y, (v).z
-/// A 4x4 affine transformation matrix, with implied [0 0 0 1] bottom row.
+/** A 4x4 affine transformation matrix, with implied [0 0 0 1] bottom row. */
typedef struct dmnsn_matrix {
- double n[3][4]; ///< The matrix elements in row-major order.
+ double n[3][4]; /**< The matrix elements in row-major order. */
} dmnsn_matrix;
-/// A standard format string for matricies.
+/** A standard format string for matricies. */
#define DMNSN_MATRIX_FORMAT \
"[%g\t%g\t%g\t%g]\n" \
"[%g\t%g\t%g\t%g]\n" \
"[%g\t%g\t%g\t%g]\n" \
"[%g\t%g\t%g\t%g]"
-/// The appropriate arguements to printf() a matrix.
+/** The appropriate arguements to printf() a matrix. */
#define DMNSN_MATRIX_PRINTF(m) \
(m).n[0][0], (m).n[0][1], (m).n[0][2], (m).n[0][3], \
(m).n[1][0], (m).n[1][1], (m).n[1][2], (m).n[1][3], \
(m).n[2][0], (m).n[2][1], (m).n[2][2], (m).n[2][3], \
0.0, 0.0, 0.0, 1.0
-/// A line, or ray.
+/** A line, or ray. */
typedef struct dmnsn_line {
- dmnsn_vector x0; ///< A point on the line.
- dmnsn_vector n; ///< A normal vector; the direction of the line.
+ dmnsn_vector x0; /**< A point on the line. */
+ dmnsn_vector n; /**< A normal vector; the direction of the line. */
} dmnsn_line;
-/// A standard format string for lines.
+/** A standard format string for lines. */
#define DMNSN_LINE_FORMAT "(<%g, %g, %g> + t*<%g, %g, %g>)"
-/// The appropriate arguements to printf() a line.
+/** The appropriate arguements to printf() a line. */
#define DMNSN_LINE_PRINTF(l) \
DMNSN_VECTOR_PRINTF((l).x0), DMNSN_VECTOR_PRINTF((l).n)
-/// An axis-aligned bounding box (AABB).
+/** An axis-aligned bounding box (AABB). */
typedef struct dmnsn_bounding_box {
- dmnsn_vector min; ///< The coordinate-wise minimum extent of the box.
- dmnsn_vector max; ///< The coordinate-wise maximum extent of the box.
+ dmnsn_vector min; /**< The coordinate-wise minimum extent of the box. */
+ dmnsn_vector max; /**< The coordinate-wise maximum extent of the box. */
} dmnsn_bounding_box;
-/// A standard format string for bounding boxes.
+/** A standard format string for bounding boxes. */
#define DMNSN_BOUNDING_BOX_FORMAT "(<%g, %g, %g> ==> <%g, %g, %g>)"
-/// The appropriate arguements to printf() a bounding box.
+/** The appropriate arguements to printf() a bounding box. */
#define DMNSN_BOUNDING_BOX_PRINTF(box) \
DMNSN_VECTOR_PRINTF((box).min), DMNSN_VECTOR_PRINTF((box).max)
-// Constants
+/* Constants */
-/// The smallest value considered non-zero by some numerical algorithms.
+/** The smallest value considered non-zero by some numerical algorithms. */
#define dmnsn_epsilon 1.0e-10
-/// The zero vector.
+/** The zero vector. */
static const dmnsn_vector dmnsn_zero = { 0.0, 0.0, 0.0 };
-/// The x vector.
+/** The x vector. */
static const dmnsn_vector dmnsn_x = { 1.0, 0.0, 0.0 };
-/// The y vector.
+/** The y vector. */
static const dmnsn_vector dmnsn_y = { 0.0, 1.0, 0.0 };
-/// The z vector.
+/** The z vector. */
static const dmnsn_vector dmnsn_z = { 0.0, 0.0, 1.0 };
-// Scalar functions
+/**
+ * @def DMNSN_INFINITY
+ * Expands to floating-point infinity.
+ */
+#if defined(INFINITY) || DMNSN_C99
+ #define DMNSN_INFINITY INFINITY
+#else
+ #define DMNSN_INFINITY HUGE_VAL
+#endif
-/// Find the minimum of two scalars.
+/* Scalar functions */
+
+/** Find the minimum of two scalars. */
DMNSN_INLINE double
dmnsn_min(double a, double b)
{
return a < b ? a : b;
}
-/// Find the maximum of two scalars.
+/** Find the maximum of two scalars. */
DMNSN_INLINE double
dmnsn_max(double a, double b)
{
return a > b ? a : b;
}
-/// Convert degrees to radians.
+/** Convert degrees to radians. */
DMNSN_INLINE double
dmnsn_radians(double degrees)
{
return degrees*atan(1.0)/45.0;
}
-/// Convert radians to degrees.
+/** Convert radians to degrees. */
DMNSN_INLINE double
dmnsn_degrees(double radians)
{
return radians*45.0/atan(1.0);
}
-/// Return the sign of a scalar.
+/** Return the sign of a scalar. */
DMNSN_INLINE int
dmnsn_sign(double n)
{
@@ -137,9 +147,9 @@ dmnsn_sign(double n)
}
}
-// Shorthand for vector/matrix construction
+/* Shorthand for vector/matrix construction */
-/// Construct a new vector.
+/** Construct a new vector. */
DMNSN_INLINE dmnsn_vector
dmnsn_new_vector(double x, double y, double z)
{
@@ -147,7 +157,7 @@ dmnsn_new_vector(double x, double y, double z)
return v;
}
-/// Construct a new transformation matrix.
+/** Construct a new transformation matrix. */
DMNSN_INLINE dmnsn_matrix
dmnsn_new_matrix(double a0, double a1, double a2, double a3,
double b0, double b1, double b2, double b3,
@@ -159,7 +169,7 @@ dmnsn_new_matrix(double a0, double a1, double a2, double a3,
return m;
}
-/// Construct a new transformation matrix from column vectors.
+/** Construct a new transformation matrix from column vectors. */
DMNSN_INLINE dmnsn_matrix
dmnsn_new_matrix4(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c,
dmnsn_vector d)
@@ -170,14 +180,14 @@ dmnsn_new_matrix4(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c,
return m;
}
-/// Extract column vectors from a matrix.
+/** Extract column vectors from a matrix. */
DMNSN_INLINE dmnsn_vector
dmnsn_matrix_column(dmnsn_matrix M, unsigned int i)
{
return dmnsn_new_vector(M.n[0][i], M.n[1][i], M.n[2][i]);
}
-/// Return the identity matrix.
+/** Return the identity matrix. */
dmnsn_matrix dmnsn_identity_matrix(void);
/**
@@ -238,119 +248,119 @@ dmnsn_new_bounding_box(dmnsn_vector min, dmnsn_vector max)
return box;
}
-/// Return the bounding box which contains nothing.
+/** Return the bounding box which contains nothing. */
DMNSN_INLINE dmnsn_bounding_box
dmnsn_zero_bounding_box(void)
{
dmnsn_bounding_box box = {
- { INFINITY, INFINITY, INFINITY },
- { -INFINITY, -INFINITY, -INFINITY }
+ { DMNSN_INFINITY, DMNSN_INFINITY, DMNSN_INFINITY },
+ { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY }
};
return box;
}
-/// Return the bounding box which contains everything.
+/** Return the bounding box which contains everything. */
DMNSN_INLINE dmnsn_bounding_box
dmnsn_infinite_bounding_box(void)
{
dmnsn_bounding_box box = {
- { -INFINITY, -INFINITY, -INFINITY },
- { INFINITY, INFINITY, INFINITY }
+ { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY },
+ { DMNSN_INFINITY, DMNSN_INFINITY, DMNSN_INFINITY }
};
return box;
}
-// Vector and matrix arithmetic
+/* Vector and matrix arithmetic */
-/// Negate a vector.
+/** Negate a vector. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_negate(dmnsn_vector rhs)
{
- // 3 negations
+ /* 3 negations */
dmnsn_vector v = { -rhs.x, -rhs.y, -rhs.z };
return v;
}
-/// Add two vectors.
+/** Add two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs)
{
- // 3 additions
+ /* 3 additions */
dmnsn_vector v = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z };
return v;
}
-/// Subtract two vectors.
+/** Subtract two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs)
{
- // 3 additions
+ /* 3 additions */
dmnsn_vector v = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z };
return v;
}
-/// Multiply a vector by a scalar.
+/** Multiply a vector by a scalar. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_mul(double lhs, dmnsn_vector rhs)
{
- // 3 multiplications
+ /* 3 multiplications */
dmnsn_vector v = { lhs*rhs.x, lhs*rhs.y, lhs*rhs.z };
return v;
}
-/// Divide a vector by a scalar.
+/** Divide a vector by a scalar. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_div(dmnsn_vector lhs, double rhs)
{
- // 3 divisions
+ /* 3 divisions */
dmnsn_vector v = { lhs.x/rhs, lhs.y/rhs, lhs.z/rhs };
return v;
}
-/// Return the dot product of two vectors.
+/** Return the dot product of two vectors. */
DMNSN_INLINE double
dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs)
{
- // 3 multiplications, 2 additions
+ /* 3 multiplications, 2 additions */
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
-/// Return the cross product of two vectors.
+/** Return the cross product of two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs)
{
- // 6 multiplications, 3 additions
+ /* 6 multiplications, 3 additions */
dmnsn_vector v = { lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x };
return v;
}
-/// Return the projection of \p u onto \p d.
+/** Return the projection of \p u onto \p d. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d)
{
- // 1 division, 9 multiplications, 4 additions
+ /* 1 division, 9 multiplications, 4 additions */
return dmnsn_vector_mul(dmnsn_vector_dot(u, d)/dmnsn_vector_dot(d, d), d);
}
-/// Return the magnitude of a vector.
+/** Return the magnitude of a vector. */
DMNSN_INLINE double
dmnsn_vector_norm(dmnsn_vector n)
{
- // 1 sqrt, 3 multiplications, 2 additions
+ /* 1 sqrt, 3 multiplications, 2 additions */
return sqrt(dmnsn_vector_dot(n, n));
}
-/// Return the direction of a vector.
+/** Return the direction of a vector. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_normalized(dmnsn_vector n)
{
- // 1 sqrt, 3 divisions, 3 multiplications, 2 additions
+ /* 1 sqrt, 3 divisions, 3 multiplications, 2 additions */
return dmnsn_vector_div(n, dmnsn_vector_norm(n));
}
-/// Return the component-wise minimum of two vectors.
+/** Return the component-wise minimum of two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b)
{
@@ -361,7 +371,7 @@ dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b)
);
}
-/// Return the component-wise maximum of two vectors.
+/** Return the component-wise maximum of two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b)
{
@@ -372,17 +382,17 @@ dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b)
);
}
-/// Invert a matrix.
+/** Invert a matrix. */
dmnsn_matrix dmnsn_matrix_inverse(dmnsn_matrix A);
-/// Multiply two matricies.
+/** Multiply two matricies. */
dmnsn_matrix dmnsn_matrix_mul(dmnsn_matrix lhs, dmnsn_matrix rhs);
-/// Transform a point by a matrix.
+/** Transform a point by a matrix. */
DMNSN_INLINE dmnsn_vector
dmnsn_transform_point(dmnsn_matrix T, dmnsn_vector v)
{
- // 9 multiplications, 9 additions
+ /* 9 multiplications, 9 additions */
dmnsn_vector r;
r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z + T.n[0][3];
r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z + T.n[1][3];
@@ -390,11 +400,11 @@ dmnsn_transform_point(dmnsn_matrix T, dmnsn_vector v)
return r;
}
-/// Transform a direction by a matrix.
+/** Transform a direction by a matrix. */
DMNSN_INLINE dmnsn_vector
dmnsn_transform_direction(dmnsn_matrix T, dmnsn_vector v)
{
- // 9 multiplications, 6 additions
+ /* 9 multiplications, 6 additions */
dmnsn_vector r;
r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z;
r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z;
@@ -411,7 +421,8 @@ dmnsn_transform_direction(dmnsn_matrix T, dmnsn_vector v)
DMNSN_INLINE dmnsn_vector
dmnsn_transform_normal(dmnsn_matrix Tinv, dmnsn_vector v)
{
- // Multiply by the transpose of the inverse (9 multiplications, 6 additions)
+ /* Multiply by the transpose of the inverse
+ (9 multiplications, 6 additions) */
dmnsn_vector r;
r.x = Tinv.n[0][0]*v.x + Tinv.n[1][0]*v.y + Tinv.n[2][0]*v.z;
r.y = Tinv.n[0][1]*v.x + Tinv.n[1][1]*v.y + Tinv.n[2][1]*v.z;
@@ -419,7 +430,7 @@ dmnsn_transform_normal(dmnsn_matrix Tinv, dmnsn_vector v)
return r;
}
-/// Transform a bounding box by a matrix.
+/** Transform a bounding box by a matrix. */
dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix T,
dmnsn_bounding_box box);
@@ -431,7 +442,7 @@ dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix T,
DMNSN_INLINE dmnsn_line
dmnsn_transform_line(dmnsn_matrix T, dmnsn_line l)
{
- // 18 multiplications, 24 additions
+ /* 18 multiplications, 24 additions */
dmnsn_line ret;
ret.x0 = dmnsn_transform_point(T, l.x0);
ret.n = dmnsn_transform_direction(T, l.n);
@@ -448,7 +459,7 @@ dmnsn_line_point(dmnsn_line l, double t)
return dmnsn_vector_add(l.x0, dmnsn_vector_mul(t, l.n));
}
-/// Add epsilon*l.n to l.x0, to avoid self-intersections.
+/** Add epsilon*l.n to l.x0, to avoid self-intersections. */
DMNSN_INLINE dmnsn_line
dmnsn_line_add_epsilon(dmnsn_line l)
{
@@ -477,7 +488,7 @@ dmnsn_symmetric_bounding_box(dmnsn_vector r)
return box;
}
-/// Return whether \p p is within the axis-aligned bounding box.
+/** Return whether \p p is within the axis-aligned bounding box. */
DMNSN_INLINE bool
dmnsn_bounding_box_contains(dmnsn_bounding_box box, dmnsn_vector p)
{
@@ -485,11 +496,11 @@ dmnsn_bounding_box_contains(dmnsn_bounding_box box, dmnsn_vector p)
&& (p.x <= box.max.x && p.y <= box.max.y && p.z <= box.max.z);
}
-/// Return whether a bounding box is infinite.
+/** Return whether a bounding box is infinite. */
DMNSN_INLINE bool
dmnsn_bounding_box_is_infinite(dmnsn_bounding_box box)
{
- return box.min.x == -INFINITY;
+ return box.min.x == -DMNSN_INFINITY;
}
/**
@@ -508,21 +519,32 @@ dmnsn_bounding_box_swallow(dmnsn_bounding_box box, dmnsn_vector point)
return ret;
}
-/// Return whether a vector contains any NaN components.
+/** Return whether a scalar is NaN. */
+DMNSN_INLINE bool
+dmnsn_isnan(double n)
+{
+#if DMNSN_C99
+ return isnan(n);
+#else
+ return n != n;
+#endif
+}
+
+/** Return whether a vector contains any NaN components. */
DMNSN_INLINE bool
dmnsn_vector_isnan(dmnsn_vector v)
{
- return isnan(v.x) || isnan(v.y) || isnan(v.z);
+ return dmnsn_isnan(v.x) || dmnsn_isnan(v.y) || dmnsn_isnan(v.z);
}
-/// Return whether a matrix contains any NaN components.
+/** Return whether a matrix contains any NaN components. */
DMNSN_INLINE bool
dmnsn_matrix_isnan(dmnsn_matrix m)
{
size_t i, j;
for (i = 0; i < 3; ++i) {
for (j = 0; j < 4; ++j) {
- if (isnan(m.n[i][j])) {
+ if (dmnsn_isnan(m.n[i][j])) {
return true;
}
}
@@ -530,14 +552,14 @@ dmnsn_matrix_isnan(dmnsn_matrix m)
return false;
}
-/// Return whether a line contains any NaN entries.
+/** Return whether a line contains any NaN entries. */
DMNSN_INLINE bool
dmnsn_line_isnan(dmnsn_line l)
{
return dmnsn_vector_isnan(l.x0) || dmnsn_vector_isnan(l.n);
}
-/// Return whether a bounding box has any NaN components.
+/** Return whether a bounding box has any NaN components. */
DMNSN_INLINE bool
dmnsn_bounding_box_isnan(dmnsn_bounding_box box)
{