BRL-CAD
mat.h
Go to the documentation of this file.
1 /* M A T . H
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2024 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 /*----------------------------------------------------------------------*/
22 
23 /** @addtogroup bn_mat
24  *
25  * @brief
26  * Matrix and vector functionality
27  */
28 /** @{ */
29 /* @file mat.h */
30 
31 #ifndef BN_MAT_H
32 #define BN_MAT_H
33 
34 #include "common.h"
35 #include <stdio.h> /* For FILE */
36 #include "vmath.h"
37 #include "bu/vls.h"
38 #include "bn/defines.h"
39 #include "bn/tol.h"
40 
41 __BEGIN_DECLS
42 
43 /*
44  * 4x4 Matrix math
45  */
46 
47 BN_EXPORT extern const mat_t bn_mat_identity;
48 
49 BN_EXPORT extern void bn_mat_print(const char *title,
50  const mat_t m);
51 
52 BN_EXPORT extern void bn_mat_print_guts(const char *title,
53  const mat_t m,
54  char *buf,
55  int buflen);
56 
57 BN_EXPORT extern void bn_mat_print_vls(const char *title,
58  const mat_t m,
59  struct bu_vls *vls);
60 
61 /**
62  * A wrapper for the system atan2(). On the Silicon Graphics, and
63  * perhaps on others, x==0 incorrectly returns infinity.
64  */
65 BN_EXPORT extern double bn_atan2(double x, double y);
66 
67 #define bn_mat_zero(_m) { \
68  bu_log("%s:%d bn_mat_zero() is deprecated, use MAT_ZERO()\n", \
69  __FILE__, __LINE__); \
70  (_m)[0] = (_m)[1] = (_m)[2] = (_m)[3] = \
71  (_m)[4] = (_m)[5] = (_m)[6] = (_m)[7] = \
72  (_m)[8] = (_m)[9] = (_m)[10] = (_m)[11] = \
73  (_m)[12] = (_m)[13] = (_m)[14] = (_m)[15] = 0.0; }
74 /*
75  #define bn_mat_zero(_m) (void)memset((void *)_m, 0, sizeof(mat_t))
76 */
77 #define bn_mat_idn(_m) { \
78  bu_log("%s:%d bn_mat_idn() is deprecated, use MAT_IDN()\n", \
79  __FILE__, __LINE__); \
80  (_m)[1] = (_m)[2] = (_m)[3] = (_m)[4] = \
81  (_m)[6] = (_m)[7] = (_m)[8] = (_m)[9] = \
82  (_m)[11] = (_m)[12] = (_m)[13] = (_m)[14] = 0.0; \
83  (_m)[0] = (_m)[5] = (_m)[10] = (_m)[15] = 1.0; }
84 /*
85  #define bn_mat_idn(_m) (void)memcpy((void *)_m, (const void *)bn_mat_identity, sizeof(mat_t))
86 */
87 
88 #define bn_mat_copy(_d, _s) { \
89  bu_log("%s:%d bn_mat_copy() is deprecated, use MAT_COPY()\n", \
90  __FILE__, __LINE__); \
91  (_d)[0] = (_s)[0];\
92  (_d)[1] = (_s)[1];\
93  (_d)[2] = (_s)[2];\
94  (_d)[3] = (_s)[3];\
95  (_d)[4] = (_s)[4];\
96  (_d)[5] = (_s)[5];\
97  (_d)[6] = (_s)[6];\
98  (_d)[7] = (_s)[7];\
99  (_d)[8] = (_s)[8];\
100  (_d)[9] = (_s)[9];\
101  (_d)[10] = (_s)[10];\
102  (_d)[11] = (_s)[11];\
103  (_d)[12] = (_s)[12];\
104  (_d)[13] = (_s)[13];\
105  (_d)[14] = (_s)[14];\
106  (_d)[15] = (_s)[15]; }
107 /*
108  #define bn_mat_copy(_d, _s) (void)memcpy((void *)_d, (const void *)(_s), sizeof(mat_t))
109 */
110 
111 
112 /**
113  * Multiply matrix "a" by "b" and store the result in "o".
114  *
115  * This is different from multiplying "b" by "a" (most of the time!)
116  * Also, "o" must not be the same as either of the inputs.
117  */
118 BN_EXPORT extern void bn_mat_mul(mat_t o,
119  const mat_t a,
120  const mat_t b);
121 
122 /**
123  * o = i * o
124  *
125  * A convenience wrapper for bn_mat_mul() to update a matrix in place.
126  * The argument ordering is confusing either way.
127  */
128 BN_EXPORT extern void bn_mat_mul2(const mat_t i,
129  mat_t o);
130 
131 /**
132  * o = a * b * c
133  *
134  * The output matrix may be the same as 'b' or 'c', but may not be
135  * 'a'.
136  */
137 BN_EXPORT extern void bn_mat_mul3(mat_t o,
138  const mat_t a,
139  const mat_t b,
140  const mat_t c);
141 
142 /**
143  * o = a * b * c * d
144  *
145  * The output matrix may be the same as any input matrix.
146  */
147 BN_EXPORT extern void bn_mat_mul4(mat_t o,
148  const mat_t a,
149  const mat_t b,
150  const mat_t c,
151  const mat_t d);
152 
153 /**
154  * Multiply the matrix "im" by the vector "iv" and store the result in
155  * the vector "ov". Note this is post-multiply, and operates on
156  * 4-tuples. Use MAT4X3VEC() to operate on 3-tuples.
157  */
158 BN_EXPORT extern void bn_matXvec(hvect_t ov,
159  const mat_t im,
160  const hvect_t iv);
161 
162 /**
163  * The matrix pointed at by "input" is inverted and stored in the area
164  * pointed at by "output".
165  *
166  * Calls bu_bomb if matrix is singular.
167  */
168 BN_EXPORT extern void bn_mat_inv(mat_t output,
169  const mat_t input);
170 
171 /**
172  * The matrix pointed at by "input" is inverted and stored in the area
173  * pointed at by "output".
174  *
175  * Invert a 4-by-4 matrix using Algorithm 120 from ACM. This is a
176  * modified Gauss-Jordan algorithm. Note: Inversion is done in place,
177  * with 3 work vectors.
178  *
179  * @return 1 if OK.
180  * @return 0 if matrix is singular.
181  */
182 BN_EXPORT extern int bn_mat_inverse(mat_t output,
183  const mat_t input);
184 
185 /**
186  * Takes a pointer to a [x, y, z] vector, and a pointer to space for a
187  * homogeneous vector [x, y, z, w], and builds [x, y, z, 1].
188  */
189 BN_EXPORT extern void bn_vtoh_move(hvect_t h,
190  const vect_t v);
191 
192 /**
193  * Takes a pointer to [x, y, z, w], and converts it to an ordinary
194  * vector [x/w, y/w, z/w]. Optimization for the case of w==1 is
195  * performed.
196  *
197  * FIXME: make tolerance configurable
198  */
199 BN_EXPORT extern void bn_htov_move(vect_t v,
200  const hvect_t h);
201 
202 BN_EXPORT extern void bn_mat_trn(mat_t om,
203  const mat_t im);
204 
205 /**
206  * Compute a 4x4 rotation matrix given Azimuth and Elevation.
207  *
208  * Azimuth is +X, Elevation is +Z, both in degrees.
209  *
210  * Formula due to Doug Gwyn, BRL.
211  */
212 BN_EXPORT extern void bn_mat_ae(mat_t m,
213  double azimuth,
214  double elev);
215 
216 /**
217  * Find the azimuth and elevation angles that correspond to the
218  * direction (not including twist) given by a direction vector.
219  */
220 BN_EXPORT extern void bn_ae_vec(fastf_t *azp,
221  fastf_t *elp,
222  const vect_t v);
223 
224 /**
225  * Find the azimuth, elevation, and twist from two vectors. Vec_ae is
226  * in the direction of view (+z in mged view) and vec_twist points to
227  * the viewers right (+x in mged view). Accuracy (degrees) is used to
228  * stabilize flutter between equivalent extremes of atan2(), and to
229  * snap twist to zero when elevation is near +/- 90
230  */
231 BN_EXPORT extern void bn_aet_vec(fastf_t *az,
232  fastf_t *el,
233  fastf_t *twist,
234  vect_t vec_ae,
235  vect_t vec_twist,
236  fastf_t accuracy);
237 
238 /**
239  * Find a unit vector from the origin given azimuth and elevation.
240  */
241 BN_EXPORT extern void bn_vec_ae(vect_t vec,
243  fastf_t el);
244 
245 /**
246  * Find a vector from the origin given azimuth, elevation, and distance.
247  */
248 BN_EXPORT extern void bn_vec_aed(vect_t vec,
250  fastf_t el,
251  fastf_t dist);
252 
253 /**
254  * This routine builds a Homogeneous rotation matrix, given alpha,
255  * beta, and gamma as angles of rotation, in degrees.
256  *
257  * Alpha is angle of rotation about the X axis, and is done third.
258  * Beta is angle of rotation about the Y axis, and is done second.
259  * Gamma is angle of rotation about Z axis, and is done first.
260  *
261  * FIXME: make tolerance configurable
262  */
263 BN_EXPORT extern void bn_mat_angles(mat_t mat,
264  double alpha,
265  double beta, double ggamma);
266 
267 /**
268  * This routine builds a Homogeneous rotation matrix, given alpha,
269  * beta, and gamma as angles of rotation, in radians.
270  *
271  * Alpha is angle of rotation about the X axis, and is done third.
272  * Beta is angle of rotation about the Y axis, and is done second.
273  * Gamma is angle of rotation about Z axis, and is done first.
274  *
275  * FIXME: make tolerance configurable
276  */
277 BN_EXPORT extern void bn_mat_angles_rad(mat_t mat,
278  double alpha,
279  double beta,
280  double ggamma);
281 
282 /**
283  * Find the eigenvalues and eigenvectors of a symmetric 2x2 matrix.
284  * (a b)
285  * (b c)
286  *
287  * The eigenvalue with the smallest absolute value is returned in
288  * val1, with its eigenvector in vec1.
289  */
290 BN_EXPORT extern void bn_eigen2x2(fastf_t *val1,
291  fastf_t *val2,
292  vect_t vec1,
293  vect_t vec2,
294  fastf_t a,
295  fastf_t b,
296  fastf_t c);
297 
298 /**
299  * Given a vector, create another vector which is perpendicular to it.
300  * The output vector will have unit length only if the input vector
301  * did.
302  *
303  * FIXME: make tolerance configurable
304  */
305 BN_EXPORT extern void bn_vec_perp(vect_t new_vec,
306  const vect_t old_vec);
307 
308 /**
309  * Given two vectors, compute a rotation matrix that will transform
310  * space by the angle between the two. There are many candidate
311  * matrices.
312  *
313  * The input 'from' and 'to' vectors need not be unit length.
314  * MAT4X3VEC(to, m, from) is the identity that is created.
315  *
316  */
317 BN_EXPORT extern void bn_mat_fromto(mat_t m,
318  const fastf_t *from,
319  const fastf_t *to,
320  const struct bn_tol *tol);
321 
322 /**
323  * Given the sin and cos of an X rotation angle, produce the rotation
324  * matrix.
325  */
326 BN_EXPORT extern void bn_mat_xrot(mat_t m,
327  double sinx,
328  double cosx);
329 
330 /**
331  * Given the sin and cos of a Y rotation angle, produce the rotation
332  * matrix.
333  */
334 BN_EXPORT extern void bn_mat_yrot(mat_t m,
335  double siny,
336  double cosy);
337 
338 /**
339  * Given the sin and cos of a Z rotation angle, produce the rotation
340  * matrix.
341  */
342 BN_EXPORT extern void bn_mat_zrot(mat_t m,
343  double sinz,
344  double cosz);
345 
346 /**
347  * Given a direction vector D of unit length, product a matrix which
348  * rotates that vector D onto the -Z axis. This matrix will be
349  * suitable for use as a "model2view" matrix.
350  *
351  * XXX This routine will fail if the vector is already more or less
352  * aligned with the Z axis.
353  *
354  * This is done in several steps.
355  *
356  @code
357  1) Rotate D about Z to match +X axis. Azimuth adjustment.
358  2) Rotate D about Y to match -Y axis. Elevation adjustment.
359  3) Rotate D about Z to make projection of X axis again point
360  in the +X direction. Twist adjustment.
361  4) Optionally, flip sign on Y axis if original Z becomes inverted.
362  This can be nice for static frames, but is astonishing when
363  used in animation.
364  @endcode
365 */
366 BN_EXPORT extern void bn_mat_lookat(mat_t rot,
367  const vect_t dir,
368  int yflip);
369 
370 /**
371  * Given a vector, create another vector which is perpendicular to it,
372  * and with unit length. This algorithm taken from Gift's arvec.f; a
373  * faster algorithm may be possible.
374  *
375  * FIXME: make tolerance configurable
376  */
377 BN_EXPORT extern void bn_vec_ortho(vect_t out,
378  const vect_t in);
379 
380 /**
381  * Build a matrix to scale uniformly around a given point.
382  *
383  * @return -1 if scale is too small.
384  * @return 0 if OK.
385  *
386  * FIXME: make tolerance configurable
387  */
388 BN_EXPORT extern int bn_mat_scale_about_pnt(mat_t mat,
389  const point_t pnt,
390  const double scale);
391 
392 /**
393  * Build a matrix to apply arbitrary 4x4 transformation around a given
394  * point.
395  */
396 BN_EXPORT extern void bn_mat_xform_about_pnt(mat_t mat,
397  const mat_t xform,
398  const point_t pnt);
399 
400 /**
401  * @return 0 When matrices are not equal
402  * @return 1 When matrices are equal
403  */
404 BN_EXPORT extern int bn_mat_is_equal(const mat_t a,
405  const mat_t b,
406  const struct bn_tol *tol);
407 
408 /**
409  * This routine is intended for detecting identity matrices read in
410  * from ascii or binary files, where the numbers are pure ones or
411  * zeros. This routine is *not* intended for tolerance-based
412  * "near-zero" comparisons; as such, it shouldn't be used on matrices
413  * which are the result of calculation.
414  *
415  *
416  * @return 0 non-identity
417  * @return 1 a perfect identity matrix
418  */
419 BN_EXPORT extern int bn_mat_is_identity(const mat_t m);
420 
421 /**
422  * Construct a transformation matrix for rotation about an arbitrary
423  * axis. The axis is defined by a point (pt) and a unit direction
424  * vector (dir). The angle of rotation is "ang"
425  *
426  * FIXME: make tolerance configurable
427  */
428 BN_EXPORT extern void bn_mat_arb_rot(mat_t m,
429  const point_t pt,
430  const vect_t dir,
431  const fastf_t ang);
432 
433 /**
434  * Return a pointer to a copy of the matrix in dynamically allocated
435  * memory.
436  */
437 BN_EXPORT extern matp_t bn_mat_dup(const mat_t in);
438 
439 /**
440  * Check to ensure that a rotation matrix preserves axis
441  * perpendicularity. Note that not all matrices are rotation
442  * matrices.
443  *
444  *
445  * @return -1 FAIL
446  * @return 0 OK
447  */
448 BN_EXPORT extern int bn_mat_ck(const char *title,
449  const mat_t m);
450 
451 /**
452  * Calculates the determinant of the 3X3 "rotation" part of the passed
453  * matrix.
454  */
455 BN_EXPORT extern fastf_t bn_mat_det3(const mat_t m);
456 
457 /**
458  * Calculates the determinant of the 4X4 matrix
459  */
460 BN_EXPORT extern fastf_t bn_mat_determinant(const mat_t m);
461 
462 /**
463  * FIXME: make tolerance configurable
464  */
465 BN_EXPORT extern int bn_mat_is_non_unif(const mat_t m);
466 
467 /**
468  * Given a model-space transformation matrix "change",
469  * return a matrix which applies the change with-respect-to
470  * given "point" and "direc".
471  */
472 BN_EXPORT extern void bn_wrt_point_direc(mat_t out,
473  const mat_t change,
474  const mat_t in,
475  const point_t point,
476  const vect_t direc,
477  const struct bn_tol *tol);
478 
479 
480 /* Matrix stuff from MGED's dozoom.c - somewhat unfinished,
481  * judging by the comments. Can probably be simplified/combined */
482 BN_EXPORT extern void persp_mat(mat_t m, fastf_t fovy, fastf_t aspect, fastf_t near1, fastf_t far1, fastf_t backoff);
483 BN_EXPORT extern void mike_persp_mat(fastf_t *pmat, const fastf_t *eye);
484 BN_EXPORT extern void deering_persp_mat(fastf_t *m, const fastf_t *l, const fastf_t *h, const fastf_t *eye);
485 
486 
487 /* Option parser/validator for libbu's option system that will read in a matrix
488  * from the argv entries. set_var should be a matp_t
489  *
490  * NOTE: In one sense this could be defined with the other option parsers in
491  * bu/opt.h, as vmath.h (which defines the matrix type) is stand-alone, but
492  * since it is defining a matrix it's a better overall conceptual fit with
493  * libbn - hence it is defined as part of that API. */
494 BN_EXPORT extern int bn_opt_mat(struct bu_vls *msg, size_t argc, const char **argv, void *set_var);
495 
496 __END_DECLS
497 
498 #endif /* BN_MAT_H */
499 /** @} */
500 /*
501  * Local Variables:
502  * mode: C
503  * tab-width: 8
504  * indent-tabs-mode: t
505  * c-file-style: "stroustrup"
506  * End:
507  * ex: shiftwidth=4 tabstop=8
508  */
Header file for the BRL-CAD common definitions.
void deering_persp_mat(fastf_t *m, const fastf_t *l, const fastf_t *h, const fastf_t *eye)
void bn_mat_lookat(mat_t rot, const vect_t dir, int yflip)
void bn_mat_print(const char *title, const mat_t m)
void bn_mat_arb_rot(mat_t m, const point_t pt, const vect_t dir, const fastf_t ang)
void bn_vtoh_move(hvect_t h, const vect_t v)
void bn_mat_xform_about_pnt(mat_t mat, const mat_t xform, const point_t pnt)
void bn_vec_perp(vect_t new_vec, const vect_t old_vec)
void bn_mat_ae(mat_t m, double azimuth, double elev)
void bn_mat_mul4(mat_t o, const mat_t a, const mat_t b, const mat_t c, const mat_t d)
void bn_wrt_point_direc(mat_t out, const mat_t change, const mat_t in, const point_t point, const vect_t direc, const struct bn_tol *tol)
void bn_mat_angles(mat_t mat, double alpha, double beta, double ggamma)
void bn_ae_vec(fastf_t *azp, fastf_t *elp, const vect_t v)
void bn_matXvec(hvect_t ov, const mat_t im, const hvect_t iv)
void bn_aet_vec(fastf_t *az, fastf_t *el, fastf_t *twist, vect_t vec_ae, vect_t vec_twist, fastf_t accuracy)
void bn_eigen2x2(fastf_t *val1, fastf_t *val2, vect_t vec1, vect_t vec2, fastf_t a, fastf_t b, fastf_t c)
void bn_mat_fromto(mat_t m, const fastf_t *from, const fastf_t *to, const struct bn_tol *tol)
void bn_htov_move(vect_t v, const hvect_t h)
int bn_mat_scale_about_pnt(mat_t mat, const point_t pnt, const double scale)
void bn_mat_mul3(mat_t o, const mat_t a, const mat_t b, const mat_t c)
void bn_mat_print_vls(const char *title, const mat_t m, struct bu_vls *vls)
void bn_vec_aed(vect_t vec, fastf_t az, fastf_t el, fastf_t dist)
void bn_mat_inv(mat_t output, const mat_t input)
void bn_mat_trn(mat_t om, const mat_t im)
void bn_mat_yrot(mat_t m, double siny, double cosy)
void bn_vec_ortho(vect_t out, const vect_t in)
int bn_opt_mat(struct bu_vls *msg, size_t argc, const char **argv, void *set_var)
const mat_t bn_mat_identity
void bn_mat_print_guts(const char *title, const mat_t m, char *buf, int buflen)
double bn_atan2(double x, double y)
void bn_mat_zrot(mat_t m, double sinz, double cosz)
void persp_mat(mat_t m, fastf_t fovy, fastf_t aspect, fastf_t near1, fastf_t far1, fastf_t backoff)
void bn_mat_mul(mat_t o, const mat_t a, const mat_t b)
void bn_mat_xrot(mat_t m, double sinx, double cosx)
int bn_mat_ck(const char *title, const mat_t m)
matp_t bn_mat_dup(const mat_t in)
fastf_t bn_mat_det3(const mat_t m)
int bn_mat_inverse(mat_t output, const mat_t input)
void bn_vec_ae(vect_t vec, fastf_t az, fastf_t el)
void bn_mat_angles_rad(mat_t mat, double alpha, double beta, double ggamma)
void bn_mat_mul2(const mat_t i, mat_t o)
int bn_mat_is_equal(const mat_t a, const mat_t b, const struct bn_tol *tol)
int bn_mat_is_non_unif(const mat_t m)
int bn_mat_is_identity(const mat_t m)
fastf_t bn_mat_determinant(const mat_t m)
void mike_persp_mat(fastf_t *pmat, const fastf_t *eye)
void int float float float * scale
Definition: tig.h:142
void float float * y
Definition: tig.h:73
void int * c
Definition: tig.h:139
void float * input
Definition: tig.h:163
void float * x
Definition: tig.h:72
fastf_t vect_t[ELEMENTS_PER_VECT]
3-tuple vector
Definition: vmath.h:349
double fastf_t
fastest 64-bit (or larger) floating point type
Definition: vmath.h:334
fastf_t mat_t[ELEMENTS_PER_MAT]
4x4 matrix
Definition: vmath.h:370
fastf_t hvect_t[ELEMENTS_PER_HVECT]
4-tuple vector
Definition: vmath.h:361
fastf_t * matp_t
pointer to a 4x4 matrix
Definition: vmath.h:373
fastf_t point_t[ELEMENTS_PER_POINT]
3-tuple point
Definition: vmath.h:355
Definition: tol.h:72
Definition: vls.h:53
Definition: geom.h:914
fundamental vector, matrix, quaternion math macros