pcb 4.1.1
An interactive printed circuit board layout editor.
|
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 }