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.h171
1 files changed, 130 insertions, 41 deletions
diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h
index adf41dc..a62fb75 100644
--- a/libdimension/dimension/geometry.h
+++ b/libdimension/dimension/geometry.h
@@ -18,7 +18,8 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-/*
+/**
+ * @file
* Core geometric types like vectors, matricies, and rays.
*/
@@ -28,74 +29,105 @@
#include <math.h>
#include <stdbool.h>
-/* Vector and matrix types */
+/** A vector in 3 dimensions. */
+typedef struct dmnsn_vector {
+ double x; /**< The x component. */
+ double y; /**< The y component. */
+ double z; /**< The z component. */
+} dmnsn_vector;
-typedef struct dmnsn_vector { double x, y, z; } dmnsn_vector;
+/** A standard format string for vectors. */
#define DMNSN_VECTOR_FORMAT "<%g, %g, %g>"
+/** The appropriate arguements to printf() a vector. */
#define DMNSN_VECTOR_PRINTF(v) (v).x, (v).y, (v).z
-typedef struct dmnsn_matrix { double n[4][4]; } dmnsn_matrix;
+/** A 4x4 affine transformation matrix. */
+typedef struct dmnsn_matrix {
+ double n[4][4]; /**< The matrix elements in row-major order. */
+} dmnsn_matrix;
+
+/** 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. */
#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], \
(m).n[3][0], (m).n[3][1], (m).n[3][2], (m).n[3][3]
-/* 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. */
#define DMNSN_LINE_FORMAT "(<%g, %g, %g> + t*<%g, %g, %g>)"
+/** The appropriate arguements to printf() a line. */
#define DMNSN_LINE_PRINTF(l) \
DMNSN_VECTOR_PRINTF((l).x0), DMNSN_VECTOR_PRINTF((l).n)
-/* A bounding box */
-typedef struct dmnsn_bounding_box { dmnsn_vector min, max; } dmnsn_bounding_box;
+/** 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_bounding_box;
+
+/** 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. */
#define DMNSN_BOUNDING_BOX_PRINTF(box) \
DMNSN_VECTOR_PRINTF((box).min), DMNSN_VECTOR_PRINTF((box).max)
/* Constants */
+/** The smallest value considered non-zero by some numerical algorithms */
#define dmnsn_epsilon 1.0e-10
+/** The zero vector */
static const dmnsn_vector dmnsn_zero = { 0.0, 0.0, 0.0 };
-static const dmnsn_vector dmnsn_x = { 1.0, 0.0, 0.0 };
-static const dmnsn_vector dmnsn_y = { 0.0, 1.0, 0.0 };
-static const dmnsn_vector dmnsn_z = { 0.0, 0.0, 1.0 };
+/** The x vector. */
+static const dmnsn_vector dmnsn_x = { 1.0, 0.0, 0.0 };
+/** The y vector. */
+static const dmnsn_vector dmnsn_y = { 0.0, 1.0, 0.0 };
+/** The z vector. */
+static const dmnsn_vector dmnsn_z = { 0.0, 0.0, 1.0 };
/* 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. */
DMNSN_INLINE double
dmnsn_max(double a, double b)
{
return a > b ? a : b;
}
+/** Convert degrees to radians */
DMNSN_INLINE double
dmnsn_radians(double degrees)
{
return degrees*atan(1.0)/45.0;
}
+/** Convert radians to degrees */
DMNSN_INLINE double
dmnsn_degrees(double radians)
{
return radians*45.0/atan(1.0);
}
+/** Return the sign bit of a scalar. */
DMNSN_INLINE int
dmnsn_signbit(double n)
{
@@ -105,6 +137,7 @@ dmnsn_signbit(double n)
/* Shorthand for vector/matrix construction */
+/** Construct a new vector */
DMNSN_INLINE dmnsn_vector
dmnsn_new_vector(double x, double y, double z)
{
@@ -112,6 +145,7 @@ dmnsn_new_vector(double x, double y, double z)
return v;
}
+/** Construct a new matrix */
DMNSN_INLINE dmnsn_matrix
dmnsn_new_matrix(double a0, double a1, double a2, double a3,
double b0, double b1, double b2, double b3,
@@ -125,12 +159,37 @@ dmnsn_new_matrix(double a0, double a1, double a2, double a3,
return m;
}
+/** Return the identity matrix */
dmnsn_matrix dmnsn_identity_matrix(void);
+
+/**
+ * A scale transformation.
+ * @param[in] s A vector with components representing the scaling factor in
+ * each axis.
+ * @return The transformation matrix.
+ */
dmnsn_matrix dmnsn_scale_matrix(dmnsn_vector s);
+/**
+ * A translation.
+ * @param[in] d The vector to translate by.
+ * @return The transformation matrix.
+ */
dmnsn_matrix dmnsn_translation_matrix(dmnsn_vector d);
-/* Left-handed rotation; theta/|theta| = axis, |theta| = angle */
+/**
+ * A left-handed rotation.
+ * @param[in] theta A vector representing an axis and angle.
+ * @f$ axis = \vec{\theta}/|\vec{\theta}| @f$,
+ * @f$ angle = |\vec{\theta}| @f$
+ * @return The transformation matrix.
+ */
dmnsn_matrix dmnsn_rotation_matrix(dmnsn_vector theta);
+/**
+ * Construct a new line.
+ * @param[in] x0 A point on the line.
+ * @param[in] n The direction of the line.
+ * @return The new line.
+ */
DMNSN_INLINE dmnsn_line
dmnsn_new_line(dmnsn_vector x0, dmnsn_vector n)
{
@@ -138,6 +197,7 @@ dmnsn_new_line(dmnsn_vector x0, dmnsn_vector n)
return l;
}
+/** Return the bounding box which contains nothing. */
DMNSN_INLINE dmnsn_bounding_box
dmnsn_zero_bounding_box(void)
{
@@ -148,6 +208,7 @@ dmnsn_zero_bounding_box(void)
return box;
}
+/** Return the bounding box which contains everything. */
DMNSN_INLINE dmnsn_bounding_box
dmnsn_infinite_bounding_box(void)
{
@@ -160,12 +221,20 @@ dmnsn_infinite_bounding_box(void)
/* Vector element access */
+/** Constants for indexing a vector like an array. */
enum {
- DMNSN_X,
- DMNSN_Y,
- DMNSN_Z
+ DMNSN_X, /**< The x component. */
+ DMNSN_Y, /**< The y component. */
+ DMNSN_Z /**< The z component. */
};
+/**
+ * Index a vector like an array.
+ * @param[in] n The vector to index.
+ * @param[in] elem Which element to access; one of \ref DMNSN_X, \ref DMNSN_Y,
+ * or \ref DMNSN_Z.
+ * @return The requested element.
+ */
DMNSN_INLINE double
dmnsn_vector_element(dmnsn_vector n, int elem)
{
@@ -179,12 +248,13 @@ dmnsn_vector_element(dmnsn_vector n, int elem)
default:
dmnsn_assert(false, "Wrong vector element requested.");
- return 0.0; /* Shut up compiler */
+ return 0.0;
}
}
/* Vector and matrix arithmetic */
+/** Negate a vector */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_negate(dmnsn_vector rhs)
{
@@ -193,6 +263,7 @@ dmnsn_vector_negate(dmnsn_vector rhs)
return v;
}
+/** Add two vectors */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs)
{
@@ -201,6 +272,7 @@ dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs)
return v;
}
+/** Subtract two vectors */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs)
{
@@ -209,6 +281,7 @@ dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs)
return v;
}
+/** Multiply a vector by a scalar. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_mul(double lhs, dmnsn_vector rhs)
{
@@ -217,6 +290,7 @@ dmnsn_vector_mul(double lhs, dmnsn_vector rhs)
return v;
}
+/** Divide a vector by a scalar. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_div(dmnsn_vector lhs, double rhs)
{
@@ -225,6 +299,7 @@ dmnsn_vector_div(dmnsn_vector lhs, double rhs)
return v;
}
+/** Return the dot product of two vectors. */
DMNSN_INLINE double
dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs)
{
@@ -232,6 +307,7 @@ dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs)
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
+/** Return the cross product of two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs)
{
@@ -242,6 +318,7 @@ dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs)
return v;
}
+/** Return the projection of \p u onto \p d. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d)
{
@@ -249,6 +326,7 @@ dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d)
return dmnsn_vector_mul(dmnsn_vector_dot(u, d)/dmnsn_vector_dot(d, d), d);
}
+/** Return the magnitude of a vector. */
DMNSN_INLINE double
dmnsn_vector_norm(dmnsn_vector n)
{
@@ -256,6 +334,7 @@ dmnsn_vector_norm(dmnsn_vector n)
return sqrt(dmnsn_vector_dot(n, n));
}
+/** Return the direction of a vector. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_normalize(dmnsn_vector n)
{
@@ -263,6 +342,7 @@ dmnsn_vector_normalize(dmnsn_vector n)
return dmnsn_vector_div(n, dmnsn_vector_norm(n));
}
+/** Return the component-wise minimum of two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b)
{
@@ -273,6 +353,7 @@ dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b)
);
}
+/** Return the component-wise maximum of two vectors. */
DMNSN_INLINE dmnsn_vector
dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b)
{
@@ -283,54 +364,65 @@ dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b)
);
}
+/** Return the angle between two vectors with respect to an axis. */
double dmnsn_vector_axis_angle(dmnsn_vector v1, dmnsn_vector v2,
dmnsn_vector axis);
+/** Invert a matrix. */
dmnsn_matrix dmnsn_matrix_inverse(dmnsn_matrix A);
+
+/** Multiply two matricies. */
dmnsn_matrix dmnsn_matrix_mul(dmnsn_matrix lhs, dmnsn_matrix rhs);
-/* Affine transformation; lhs*(x,y,z,1), normalized so the fourth element is
- 1 */
+/** Transform a vector by a matrix. */
DMNSN_INLINE dmnsn_vector
-dmnsn_transform_vector(dmnsn_matrix lhs, dmnsn_vector rhs)
+dmnsn_transform_vector(dmnsn_matrix T, dmnsn_vector v)
{
/* 12 multiplications, 3 divisions, 12 additions */
dmnsn_vector r;
double w;
- r.x = lhs.n[0][0]*rhs.x + lhs.n[0][1]*rhs.y + lhs.n[0][2]*rhs.z + lhs.n[0][3];
- r.y = lhs.n[1][0]*rhs.x + lhs.n[1][1]*rhs.y + lhs.n[1][2]*rhs.z + lhs.n[1][3];
- r.z = lhs.n[2][0]*rhs.x + lhs.n[2][1]*rhs.y + lhs.n[2][2]*rhs.z + lhs.n[2][3];
- w = lhs.n[3][0]*rhs.x + lhs.n[3][1]*rhs.y + lhs.n[3][2]*rhs.z + lhs.n[3][3];
+ 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];
+ r.z = T.n[2][0]*v.x + T.n[2][1]*v.y + T.n[2][2]*v.z + T.n[2][3];
+ w = T.n[3][0]*v.x + T.n[3][1]*v.y + T.n[3][2]*v.z + T.n[3][3];
return dmnsn_vector_div(r, w);
}
-dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix lhs,
- dmnsn_bounding_box rhs);
+/** Transform a bounding box by a matrix. */
+dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix T,
+ dmnsn_bounding_box box);
-/* Affine line transformation; n = lhs*(x0 + n) - lhs*x0, x0 *= lhs */
+/**
+ * Transform a line by a matrix.
+ * \f$ n' = T(l.\vec{x_0} + l.\vec{n}) - T(l.\vec{x_0}) \f$,
+ * \f$ \vec{x_0}' = T(l.\vec{x_0}) \f$
+ */
DMNSN_INLINE dmnsn_line
-dmnsn_transform_line(dmnsn_matrix lhs, dmnsn_line rhs)
+dmnsn_transform_line(dmnsn_matrix T, dmnsn_line l)
{
/* 24 multiplications, 6 divisions, 30 additions */
- dmnsn_line l;
- l.x0 = dmnsn_transform_vector(lhs, rhs.x0);
- l.n = dmnsn_vector_sub(
- dmnsn_transform_vector(lhs, dmnsn_vector_add(rhs.x0, rhs.n)),
- l.x0
+ dmnsn_line ret;
+ ret.x0 = dmnsn_transform_vector(T, l.x0);
+ ret.n = dmnsn_vector_sub(
+ dmnsn_transform_vector(T, dmnsn_vector_add(l.x0, l.n)),
+ ret.x0
);
- return l;
+ return ret;
}
-/* A point on a line, defined by x0 + t*n */
+/**
+ * Return the point at \p t on a line.
+ * The point is defined by \f$ l.\vec{x_0} + t \cdot l.\vec{n} \f$
+ */
DMNSN_INLINE dmnsn_vector
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)
{
@@ -343,10 +435,7 @@ dmnsn_line_add_epsilon(dmnsn_line l)
);
}
-/* Solve for the t value such that x0 + t*n = x */
-double dmnsn_line_index(dmnsn_line l, dmnsn_vector x);
-
-/* Return whether 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)
{
@@ -354,7 +443,7 @@ 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 `box' is infinite */
+/** Return whether a bounding box is infinite */
DMNSN_INLINE bool
dmnsn_bounding_box_is_infinite(dmnsn_bounding_box box)
{