pcb 4.1.1
An interactive printed circuit board layout editor.

matrix.c

Go to the documentation of this file.
00001 /* GTS - Library for the manipulation of triangulated surfaces
00002  * Copyright (C) 1999 Stéphane Popinet
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 #include <math.h>
00021 #include "gts.h"
00022 
00046 GtsMatrix * gts_matrix_new (gdouble a00, gdouble a01, gdouble a02, gdouble a03,
00047                             gdouble a10, gdouble a11, gdouble a12, gdouble a13,
00048                             gdouble a20, gdouble a21, gdouble a22, gdouble a23,
00049                             gdouble a30, gdouble a31, gdouble a32, gdouble a33)
00050 {
00051   GtsMatrix * m;
00052 
00053   m = g_malloc (4*sizeof (GtsVector4));
00054 
00055   m[0][0] = a00; m[1][0] = a10; m[2][0] = a20; m[3][0] = a30;
00056   m[0][1] = a01; m[1][1] = a11; m[2][1] = a21; m[3][1] = a31;
00057   m[0][2] = a02; m[1][2] = a12; m[2][2] = a22; m[3][2] = a32;
00058   m[0][3] = a03; m[1][3] = a13; m[2][3] = a23; m[3][3] = a33;
00059 
00060   return m;
00061 }
00062 
00085 void gts_matrix_assign (GtsMatrix * m,
00086                         gdouble a00, gdouble a01, gdouble a02, gdouble a03,
00087                         gdouble a10, gdouble a11, gdouble a12, gdouble a13,
00088                         gdouble a20, gdouble a21, gdouble a22, gdouble a23,
00089                         gdouble a30, gdouble a31, gdouble a32, gdouble a33)
00090 {
00091   g_return_if_fail (m != NULL);
00092 
00093   m[0][0] = a00; m[1][0] = a10; m[2][0] = a20; m[3][0] = a30;
00094   m[0][1] = a01; m[1][1] = a11; m[2][1] = a21; m[3][1] = a31;
00095   m[0][2] = a02; m[1][2] = a12; m[2][2] = a22; m[3][2] = a32;
00096   m[0][3] = a03; m[1][3] = a13; m[2][3] = a23; m[3][3] = a33;
00097 }
00098 
00108 GtsMatrix * gts_matrix_projection (GtsTriangle * t)
00109 {
00110   GtsVertex * v1, * v2, * v3;
00111   GtsEdge * e1, * e2, * e3;
00112   GtsMatrix * m;
00113   gdouble x1, y1, z1, x2, y2, z2, x3, y3, z3, l;
00114   
00115   g_return_val_if_fail (t != NULL, NULL);
00116 
00117   m = g_malloc (4*sizeof (GtsVector4));
00118   gts_triangle_vertices_edges (t, NULL, &v1, &v2, &v3, &e1, &e2, &e3);
00119 
00120   x1 = GTS_POINT (v2)->x - GTS_POINT (v1)->x; 
00121   y1 = GTS_POINT (v2)->y - GTS_POINT (v1)->y; 
00122   z1 = GTS_POINT (v2)->z - GTS_POINT (v1)->z;
00123   x2 = GTS_POINT (v3)->x - GTS_POINT (v1)->x; 
00124   y2 = GTS_POINT (v3)->y - GTS_POINT (v1)->y; 
00125   z2 = GTS_POINT (v3)->z - GTS_POINT (v1)->z;
00126   x3 = y1*z2 - z1*y2; y3 = z1*x2 - x1*z2; z3 = x1*y2 - y1*x2;
00127   x2 = y3*z1 - z3*y1; y2 = z3*x1 - x3*z1; z2 = x3*y1 - y3*x1;
00128 
00129   l = sqrt (x1*x1 + y1*y1 + z1*z1);
00130   g_assert (l > 0.0);
00131   m[0][0] = x1/l; m[1][0] = y1/l; m[2][0] = z1/l; m[3][0] = 0.;
00132   l = sqrt (x2*x2 + y2*y2 + z2*z2);
00133   g_assert (l > 0.0);
00134   m[0][1] = x2/l; m[1][1] = y2/l; m[2][1] = z2/l; m[3][1] = 0.;
00135   l = sqrt (x3*x3 + y3*y3 + z3*z3);
00136   g_assert (l > 0.0);
00137   m[0][2] = x3/l; m[1][2] = y3/l; m[2][2] = z3/l; m[3][2] = 0.;
00138   m[0][3] = 0; m[1][3] = 0.; m[2][3] = 0.; m[3][3] = 1.;
00139 
00140   return m;
00141 }
00142 
00149 GtsMatrix * gts_matrix_transpose (GtsMatrix * m)
00150 {
00151   GtsMatrix * mi;
00152 
00153   g_return_val_if_fail (m != NULL, NULL);
00154 
00155   mi = g_malloc (4*sizeof (GtsVector4));
00156 
00157   mi[0][0] = m[0][0]; mi[1][0] = m[0][1]; 
00158   mi[2][0] = m[0][2]; mi[3][0] = m[0][3];
00159   mi[0][1] = m[1][0]; mi[1][1] = m[1][1]; 
00160   mi[2][1] = m[1][2]; mi[3][1] = m[1][3];
00161   mi[0][2] = m[2][0]; mi[1][2] = m[2][1]; 
00162   mi[2][2] = m[2][2]; mi[3][2] = m[2][3];
00163   mi[0][3] = m[3][0]; mi[1][3] = m[3][1]; 
00164   mi[2][3] = m[3][2]; mi[3][3] = m[3][3];
00165 
00166   return mi;
00167 }
00168 
00169 /*
00170  * calculate the determinant of a 2x2 matrix.
00171  * 
00172  * Adapted from:
00173  * Matrix Inversion
00174  * by Richard Carling
00175  * from "Graphics Gems", Academic Press, 1990
00176  */
00177 static gdouble det2x2 (gdouble a, gdouble b, gdouble c, gdouble d)
00178 {
00179   gdouble ans2;
00180 
00181   ans2 = a*d - b*c;
00182   return ans2;
00183 }
00184 
00185 /*
00186  * calculate the determinant of a 3x3 matrix
00187  * in the form
00188  *
00189  *     | a1,  b1,  c1 |
00190  *     | a2,  b2,  c2 |
00191  *     | a3,  b3,  c3 |
00192  *
00193  * Adapted from:
00194  * Matrix Inversion
00195  * by Richard Carling
00196  * from "Graphics Gems", Academic Press, 1990
00197  */
00198 static gdouble det3x3 (gdouble a1, gdouble a2, gdouble a3, 
00199                        gdouble b1, gdouble b2, gdouble b3, 
00200                        gdouble c1, gdouble c2, gdouble c3)
00201 {
00202   gdouble ans3;
00203 
00204   ans3 = a1 * det2x2( b2, b3, c2, c3 )
00205     - b1 * det2x2( a2, a3, c2, c3 )
00206     + c1 * det2x2( a2, a3, b2, b3 );
00207   return ans3;
00208 }
00209 
00216 gdouble gts_matrix_determinant (GtsMatrix * m)
00217 {
00218   gdouble ans4;
00219   gdouble a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
00220 
00221   g_return_val_if_fail (m != NULL, 0.0);
00222 
00223   a1 = m[0][0]; b1 = m[0][1]; 
00224   c1 = m[0][2]; d1 = m[0][3];
00225   
00226   a2 = m[1][0]; b2 = m[1][1]; 
00227   c2 = m[1][2]; d2 = m[1][3];
00228   
00229   a3 = m[2][0]; b3 = m[2][1]; 
00230   c3 = m[2][2]; d3 = m[2][3];
00231   
00232   a4 = m[3][0]; b4 = m[3][1]; 
00233   c4 = m[3][2]; d4 = m[3][3];
00234   
00235   ans4 = a1 * det3x3 (b2, b3, b4, c2, c3, c4, d2, d3, d4)
00236     - b1 * det3x3 (a2, a3, a4, c2, c3, c4, d2, d3, d4)
00237     + c1 * det3x3 (a2, a3, a4, b2, b3, b4, d2, d3, d4)
00238     - d1 * det3x3 (a2, a3, a4, b2, b3, b4, c2, c3, c4);
00239 
00240   return ans4;
00241 }
00242 
00243 /* 
00244  *   adjoint( original_matrix, inverse_matrix )
00245  * 
00246  *     calculate the adjoint of a 4x4 matrix
00247  *
00248  *      Let  a   denote the minor determinant of matrix A obtained by
00249  *           ij
00250  *
00251  *      deleting the ith row and jth column from A.
00252  *
00253  *                    i+j
00254  *     Let  b   = (-1)    a
00255  *          ij            ji
00256  *
00257  *    The matrix B = (b  ) is the adjoint of A
00258  *                     ij
00259  */
00260 static GtsMatrix * adjoint (GtsMatrix * m)
00261 {
00262   gdouble a1, a2, a3, a4, b1, b2, b3, b4;
00263   gdouble c1, c2, c3, c4, d1, d2, d3, d4;
00264   GtsMatrix * ma;
00265 
00266   a1 = m[0][0]; b1 = m[0][1]; 
00267   c1 = m[0][2]; d1 = m[0][3];
00268   
00269   a2 = m[1][0]; b2 = m[1][1]; 
00270   c2 = m[1][2]; d2 = m[1][3];
00271   
00272   a3 = m[2][0]; b3 = m[2][1];
00273   c3 = m[2][2]; d3 = m[2][3];
00274   
00275   a4 = m[3][0]; b4 = m[3][1]; 
00276   c4 = m[3][2]; d4 = m[3][3];
00277 
00278   ma = g_malloc (4*sizeof (GtsVector4));
00279 
00280   /* row column labeling reversed since we transpose rows & columns */
00281 
00282   ma[0][0]  =   det3x3 (b2, b3, b4, c2, c3, c4, d2, d3, d4);
00283   ma[1][0]  = - det3x3 (a2, a3, a4, c2, c3, c4, d2, d3, d4);
00284   ma[2][0]  =   det3x3 (a2, a3, a4, b2, b3, b4, d2, d3, d4);
00285   ma[3][0]  = - det3x3 (a2, a3, a4, b2, b3, b4, c2, c3, c4);
00286   
00287   ma[0][1]  = - det3x3 (b1, b3, b4, c1, c3, c4, d1, d3, d4);
00288   ma[1][1]  =   det3x3 (a1, a3, a4, c1, c3, c4, d1, d3, d4);
00289   ma[2][1]  = - det3x3 (a1, a3, a4, b1, b3, b4, d1, d3, d4);
00290   ma[3][1]  =   det3x3 (a1, a3, a4, b1, b3, b4, c1, c3, c4);
00291   
00292   ma[0][2]  =   det3x3 (b1, b2, b4, c1, c2, c4, d1, d2, d4);
00293   ma[1][2]  = - det3x3 (a1, a2, a4, c1, c2, c4, d1, d2, d4);
00294   ma[2][2]  =   det3x3 (a1, a2, a4, b1, b2, b4, d1, d2, d4);
00295   ma[3][2]  = - det3x3 (a1, a2, a4, b1, b2, b4, c1, c2, c4);
00296   
00297   ma[0][3]  = - det3x3 (b1, b2, b3, c1, c2, c3, d1, d2, d3);
00298   ma[1][3]  =   det3x3 (a1, a2, a3, c1, c2, c3, d1, d2, d3);
00299   ma[2][3]  = - det3x3 (a1, a2, a3, b1, b2, b3, d1, d2, d3);
00300   ma[3][3]  =   det3x3 (a1, a2, a3, b1, b2, b3, c1, c2, c3);
00301   
00302   return ma;
00303 }
00304 
00305 
00313 GtsMatrix * gts_matrix_inverse (GtsMatrix * m)
00314 {
00315   GtsMatrix * madj;
00316   gdouble det;
00317   gint i, j;
00318 
00319   g_return_val_if_fail (m != NULL, NULL);
00320   
00321   det = gts_matrix_determinant (m);
00322   if (det == 0.)
00323     return NULL;
00324 
00325   madj = adjoint (m);
00326   for (i = 0; i < 4; i++)
00327     for(j = 0; j < 4; j++)
00328       madj[i][j] /= det;
00329 
00330   return madj;
00331 }
00332 
00340 GtsMatrix * gts_matrix3_inverse (GtsMatrix * m)
00341 {
00342   GtsMatrix * mi;
00343   gdouble det;
00344 
00345   g_return_val_if_fail (m != NULL, NULL);
00346   
00347   det = (m[0][0]*(m[1][1]*m[2][2] - m[2][1]*m[1][2]) - 
00348          m[0][1]*(m[1][0]*m[2][2] - m[2][0]*m[1][2]) + 
00349          m[0][2]*(m[1][0]*m[2][1] - m[2][0]*m[1][1]));
00350   if (det == 0.0)
00351     return NULL;
00352 
00353   mi = g_malloc0 (4*sizeof (GtsVector));
00354 
00355   mi[0][0] = (m[1][1]*m[2][2] - m[1][2]*m[2][1])/det; 
00356   mi[0][1] = (m[2][1]*m[0][2] - m[0][1]*m[2][2])/det;
00357   mi[0][2] = (m[0][1]*m[1][2] - m[1][1]*m[0][2])/det; 
00358   mi[1][0] = (m[1][2]*m[2][0] - m[1][0]*m[2][2])/det; 
00359   mi[1][1] = (m[0][0]*m[2][2] - m[2][0]*m[0][2])/det; 
00360   mi[1][2] = (m[1][0]*m[0][2] - m[0][0]*m[1][2])/det; 
00361   mi[2][0] = (m[1][0]*m[2][1] - m[2][0]*m[1][1])/det; 
00362   mi[2][1] = (m[2][0]*m[0][1] - m[0][0]*m[2][1])/det; 
00363   mi[2][2] = (m[0][0]*m[1][1] - m[0][1]*m[1][0])/det; 
00364 
00365   return mi;
00366 }
00367 
00375 void gts_matrix_print (GtsMatrix * m, FILE * fptr)
00376 {
00377   g_return_if_fail (m != NULL);
00378   g_return_if_fail (fptr != NULL);
00379 
00380   fprintf (fptr, 
00381            "[[%15.7g %15.7g %15.7g %15.7g]\n"
00382            " [%15.7g %15.7g %15.7g %15.7g]\n"
00383            " [%15.7g %15.7g %15.7g %15.7g]\n"
00384            " [%15.7g %15.7g %15.7g %15.7g]]\n",
00385            m[0][0], m[0][1], m[0][2], m[0][3],
00386            m[1][0], m[1][1], m[1][2], m[1][3],
00387            m[2][0], m[2][1], m[2][2], m[2][3],
00388            m[3][0], m[3][1], m[3][2], m[3][3]);
00389 }
00390 
00398 void gts_vector_print (GtsVector v, FILE * fptr)
00399 {
00400   g_return_if_fail (fptr != NULL);
00401 
00402   fprintf (fptr, 
00403            "[%15.7g %15.7g %15.7g ]\n",
00404            v[0], v[1], v[2]);
00405 }
00406 
00414 void gts_vector4_print (GtsVector4 v, FILE * fptr)
00415 {
00416   g_return_if_fail (fptr != NULL);
00417 
00418   fprintf (fptr, 
00419            "[%15.7g %15.7g %15.7g %15.7g]\n",
00420            v[0], v[1], v[2], v[3]);
00421 }
00422 
00423 /* [cos(alpha)]^2 */
00424 #define COSALPHA2 0.999695413509 /* alpha = 1 degree */
00425 /* [sin(alpha)]^2 */
00426 #define SINALPHA2 3.04586490453e-4 /* alpha = 1 degree */
00427 
00443 guint gts_matrix_compatible_row (GtsMatrix * A,
00444                                  GtsVector b,
00445                                  guint n,
00446                                  GtsVector A1,
00447                                  gdouble b1)
00448 {
00449   gdouble na1;
00450   
00451   g_return_val_if_fail (A != NULL, 0);
00452 
00453   na1 = gts_vector_scalar (A1, A1);
00454   if (na1 == 0.0)
00455     return n;
00456 
00457   /* normalize row */
00458   na1 = sqrt (na1);
00459   A1[0] /= na1; A1[1] /= na1; A1[2] /= na1; b1 /= na1;
00460 
00461   if (n == 1) {
00462     gdouble a0a1 = gts_vector_scalar (A[0], A1);
00463     if (a0a1*a0a1 >= COSALPHA2)
00464       return 1;
00465   }
00466   else if (n == 2) {
00467     GtsVector V;
00468     gdouble s;
00469     
00470     gts_vector_cross (V, A[0], A[1]);
00471     s = gts_vector_scalar (V, A1);
00472     if (s*s <= gts_vector_scalar (V, V)*SINALPHA2)
00473       return 2;
00474   }
00475 
00476   A[n][0] = A1[0]; A[n][1] = A1[1]; A[n][2] = A1[2]; b[n] = b1;
00477   return n + 1;
00478 }
00479 
00498 guint gts_matrix_quadratic_optimization (GtsMatrix * A,
00499                                          GtsVector b,
00500                                          guint n,
00501                                          GtsMatrix * H,
00502                                          GtsVector c)
00503 {
00504   g_return_val_if_fail (A != NULL, 0);
00505   g_return_val_if_fail (b != NULL, 0);
00506   g_return_val_if_fail (n < 3, 0);
00507   g_return_val_if_fail (H != NULL, 0);
00508 
00509   switch (n) {
00510   case 0: {
00511     n = gts_matrix_compatible_row (A, b, n, H[0], - c[0]);
00512     n = gts_matrix_compatible_row (A, b, n, H[1], - c[1]);
00513     n = gts_matrix_compatible_row (A, b, n, H[2], - c[2]);
00514     return n;
00515   }
00516   case 1: {
00517     GtsVector Q0 = {0., 0., 0.};
00518     GtsVector Q1 = {0., 0., 0.};
00519     GtsVector A1;
00520     gdouble max = A[0][0]*A[0][0];
00521     guint d = 0;
00522 
00523     /* build a vector orthogonal to the constraint */
00524     if (A[0][1]*A[0][1] > max) { max = A[0][1]*A[0][1]; d = 1; }
00525     if (A[0][2]*A[0][2] > max) { max = A[0][2]*A[0][2]; d = 2; }
00526     switch (d) {
00527     case 0: Q0[0] = - A[0][2]/A[0][0]; Q0[2] = 1.0; break;
00528     case 1: Q0[1] = - A[0][2]/A[0][1]; Q0[2] = 1.0; break;
00529     case 2: Q0[2] = - A[0][0]/A[0][2]; Q0[0] = 1.0; break;
00530     }
00531 
00532     /* build a second vector orthogonal to the first and to the constraint */
00533     gts_vector_cross (Q1, A[0], Q0);
00534 
00535     A1[0] = gts_vector_scalar (Q0, H[0]);
00536     A1[1] = gts_vector_scalar (Q0, H[1]);
00537     A1[2] = gts_vector_scalar (Q0, H[2]);
00538 
00539     n = gts_matrix_compatible_row (A, b, n, A1, - gts_vector_scalar (Q0, c));
00540     
00541     A1[0] = gts_vector_scalar (Q1, H[0]);
00542     A1[1] = gts_vector_scalar (Q1, H[1]);
00543     A1[2] = gts_vector_scalar (Q1, H[2]);
00544 
00545     n = gts_matrix_compatible_row (A, b, n, A1, - gts_vector_scalar (Q1, c));
00546 
00547     return n;
00548   }
00549   case 2: {
00550     /* build a vector orthogonal to the two constraints */
00551     GtsVector A1, Q;
00552 
00553     gts_vector_cross (Q, A[0], A[1]);
00554     A1[0] = gts_vector_scalar (Q, H[0]);
00555     A1[1] = gts_vector_scalar (Q, H[1]);
00556     A1[2] = gts_vector_scalar (Q, H[2]);
00557     
00558     n = gts_matrix_compatible_row (A, b, n, A1, - gts_vector_scalar (Q, c));
00559 
00560     return n;
00561   }
00562   default:
00563     g_assert_not_reached ();
00564   }
00565   return 0;
00566 }
00567 
00574 void gts_matrix_destroy (GtsMatrix * m)
00575 {
00576   g_free (m);
00577 }
00578 
00586 GtsMatrix * gts_matrix_product (GtsMatrix * m1, GtsMatrix * m2)
00587 {
00588   guint i, j;
00589   GtsMatrix * m;
00590 
00591   g_return_val_if_fail (m1 != NULL, NULL);
00592   g_return_val_if_fail (m2 != NULL, NULL);
00593   g_return_val_if_fail (m1 != m2, NULL);
00594 
00595   m = g_malloc (4*sizeof (GtsVector4));
00596 
00597   for (i = 0; i < 4; i++)
00598     for (j = 0; j < 4; j++)
00599       m[i][j] = m1[i][0]*m2[0][j] + m1[i][1]*m2[1][j] +
00600         m1[i][2]*m2[2][j] + m1[i][3]*m2[3][j];
00601   return m;
00602 }
00603 
00612 GtsMatrix * gts_matrix_zero (GtsMatrix * m)
00613 {
00614   if (m == NULL)
00615     m = g_malloc0 (4*sizeof (GtsVector4));
00616   else {
00617     m[0][0] = m[1][0] = m[2][0] = m[3][0] = 0.;
00618     m[0][1] = m[1][1] = m[2][1] = m[3][1] = 0.;
00619     m[0][2] = m[1][2] = m[2][2] = m[3][2] = 0.;
00620     m[0][3] = m[1][3] = m[2][3] = m[3][3] = 0.;
00621   }
00622   return m;
00623 }
00624 
00633 GtsMatrix * gts_matrix_identity (GtsMatrix * m)
00634 {
00635   m = gts_matrix_zero (m);
00636   m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.;
00637   return m;
00638 }
00639 
00650 GtsMatrix * gts_matrix_scale (GtsMatrix * m, GtsVector s)
00651 {
00652   m = gts_matrix_zero (m);
00653   m[0][0] = s[0];
00654   m[1][1] = s[1];
00655   m[2][2] = s[2];
00656   m[3][3] = 1.;
00657   return m;
00658 }
00659 
00670 GtsMatrix * gts_matrix_translate (GtsMatrix * m, GtsVector t)
00671 {
00672   m = gts_matrix_zero (m);
00673   m[0][3] = t[0];
00674   m[1][3] = t[1];
00675   m[2][3] = t[2];
00676   m[3][3] = 1.;
00677   m[0][0] = m[1][1] = m[2][2] = 1.;
00678   return m;
00679 }
00680 
00692 GtsMatrix * gts_matrix_rotate (GtsMatrix * m,
00693                                GtsVector r,
00694                                gdouble angle)
00695 {
00696   gdouble c, c1, s;
00697 
00698   gts_vector_normalize (r);
00699 
00700   c = cos (angle);
00701   c1 = 1. - c;
00702   s = sin (angle);
00703 
00704   if (m == NULL)
00705     m = g_malloc (4*sizeof (GtsVector4));
00706 
00707   m[0][0] = r[0]*r[0]*c1 + c;
00708   m[0][1] = r[0]*r[1]*c1 - r[2]*s;
00709   m[0][2] = r[0]*r[2]*c1 + r[1]*s;
00710   m[0][3] = 0.;
00711 
00712   m[1][0] = r[1]*r[0]*c1 + r[2]*s;
00713   m[1][1] = r[1]*r[1]*c1 + c;
00714   m[1][2] = r[1]*r[2]*c1 - r[0]*s;
00715   m[1][3] = 0.;
00716 
00717   m[2][0] = r[2]*r[0]*c1 - r[1]*s;
00718   m[2][1] = r[2]*r[1]*c1 + r[0]*s;
00719   m[2][2] = r[2]*r[2]*c1 + c;
00720   m[2][3] = 0.;
00721 
00722   m[3][0] = 0.;
00723   m[3][1] = 0.;
00724   m[3][2] = 0.;
00725   m[3][3] = 1.;
00726 
00727   return m;
00728 }