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 "gts.h" 00021 00022 typedef enum { LEFT = 0, RIGHT = 1 } Orientation; 00023 00024 typedef struct { 00025 GtsVertex * v; 00026 Orientation orientation; 00027 } OrientedVertex; 00028 00029 struct _GtsIsoSlice { 00030 OrientedVertex *** vertices; 00031 guint nx, ny; 00032 }; 00033 00034 /* coordinates of the edges of the cube (see doc/isocube.fig) */ 00035 static guint c[12][4] = { 00036 {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 1}, {0, 0, 1, 0}, 00037 {1, 0, 0, 0}, {1, 0, 0, 1}, {1, 1, 0, 1}, {1, 1, 0, 0}, 00038 {2, 0, 0, 0}, {2, 1, 0, 0}, {2, 1, 1, 0}, {2, 0, 1, 0}}; 00039 00040 /* first index is the edge number, second index is the edge orientation 00041 (RIGHT or LEFT), third index are the edges which this edge may connect to 00042 in order */ 00043 static guint edge[12][2][3] = { 00044 {{9, 1, 8}, {4, 3, 7}}, /* 0 */ 00045 {{6, 2, 5}, {8, 0, 9}}, /* 1 */ 00046 {{10, 3, 11}, {5, 1, 6}}, /* 2 */ 00047 {{7, 0, 4}, {11, 2, 10}}, /* 3 */ 00048 {{3, 7, 0}, {8, 5, 11}}, /* 4 */ 00049 {{11, 4, 8}, {1, 6, 2}}, /* 5 */ 00050 {{2, 5, 1}, {9, 7, 10}}, /* 6 */ 00051 {{10, 6, 9}, {0, 4, 3}}, /* 7 */ 00052 {{5, 11, 4}, {0, 9, 1}}, /* 8 */ 00053 {{1, 8, 0}, {7, 10, 6}}, /* 9 */ 00054 {{6, 9, 7}, {3, 11, 2}}, /* 10 */ 00055 {{2, 10, 3}, {4, 8, 5}} /* 11 */ 00056 }; 00057 00058 static void ** malloc2D (guint nx, guint ny, gulong size) 00059 { 00060 void ** m = g_malloc (nx*sizeof (void *)); 00061 guint i; 00062 00063 for (i = 0; i < nx; i++) 00064 m[i] = g_malloc0 (ny*size); 00065 00066 return m; 00067 } 00068 00069 static void free2D (void ** m, guint nx) 00070 { 00071 guint i; 00072 00073 g_return_if_fail (m != NULL); 00074 00075 for (i = 0; i < nx; i++) 00076 g_free (m[i]); 00077 g_free (m); 00078 } 00079 00087 GtsGridPlane * gts_grid_plane_new (guint nx, guint ny) 00088 { 00089 GtsGridPlane * g = g_malloc (sizeof (GtsGridPlane)); 00090 00091 g->p = (GtsPoint **) malloc2D (nx, ny, sizeof (GtsPoint)); 00092 g->nx = nx; 00093 g->ny = ny; 00094 00095 return g; 00096 } 00097 00103 void gts_grid_plane_destroy (GtsGridPlane * g) 00104 { 00105 g_return_if_fail (g != NULL); 00106 00107 free2D ((void **) g->p, g->nx); 00108 g_free (g); 00109 } 00110 00118 GtsIsoSlice * gts_iso_slice_new (guint nx, guint ny) 00119 { 00120 GtsIsoSlice * slice; 00121 00122 g_return_val_if_fail (nx > 1, NULL); 00123 g_return_val_if_fail (ny > 1, NULL); 00124 00125 slice = g_malloc (sizeof (GtsIsoSlice)); 00126 00127 slice->vertices = g_malloc (3*sizeof (OrientedVertex **)); 00128 slice->vertices[0] = 00129 (OrientedVertex **) malloc2D (nx, ny, sizeof (OrientedVertex)); 00130 slice->vertices[1] = 00131 (OrientedVertex **) malloc2D (nx - 1, ny, sizeof (OrientedVertex)); 00132 slice->vertices[2] = 00133 (OrientedVertex **) malloc2D (nx, ny - 1, sizeof (OrientedVertex)); 00134 slice->nx = nx; 00135 slice->ny = ny; 00136 00137 return slice; 00138 } 00139 00154 void gts_iso_slice_fill (GtsIsoSlice * slice, 00155 GtsGridPlane * plane1, 00156 GtsGridPlane * plane2, 00157 gdouble ** f1, 00158 gdouble ** f2, 00159 gdouble iso, 00160 GtsVertexClass * klass) 00161 { 00162 OrientedVertex *** vertices; 00163 GtsPoint ** p1, ** p2 = NULL; 00164 guint i, j, nx, ny; 00165 00166 g_return_if_fail (slice != NULL); 00167 g_return_if_fail (plane1 != NULL); 00168 g_return_if_fail (f1 != NULL); 00169 g_return_if_fail (f2 == NULL || plane2 != NULL); 00170 00171 p1 = plane1->p; 00172 if (plane2) 00173 p2 = plane2->p; 00174 vertices = slice->vertices; 00175 nx = slice->nx; 00176 ny = slice->ny; 00177 00178 if (f2) 00179 for (i = 0; i < nx; i++) 00180 for (j = 0; j < ny; j++) { 00181 gdouble v1 = f1[i][j] - iso; 00182 gdouble v2 = f2[i][j] - iso; 00183 if ((v1 >= 0. && v2 < 0.) || (v1 < 0. && v2 >= 0.)) { 00184 gdouble c2 = v1/(v1 - v2), c1 = 1. - c2; 00185 vertices[0][i][j].v = 00186 gts_vertex_new (klass, 00187 c1*p1[i][j].x + c2*p2[i][j].x, 00188 c1*p1[i][j].y + c2*p2[i][j].y, 00189 c1*p1[i][j].z + c2*p2[i][j].z); 00190 vertices[0][i][j].orientation = v2 >= 0. ? RIGHT : LEFT; 00191 } 00192 else 00193 vertices[0][i][j].v = NULL; 00194 } 00195 for (i = 0; i < nx - 1; i++) 00196 for (j = 0; j < ny; j++) { 00197 gdouble v1 = f1[i][j] - iso; 00198 gdouble v2 = f1[i+1][j] - iso; 00199 if ((v1 >= 0. && v2 < 0.) || (v1 < 0. && v2 >= 0.)) { 00200 gdouble c2 = v1/(v1 - v2), c1 = 1. - c2; 00201 vertices[1][i][j].v = 00202 gts_vertex_new (klass, 00203 c1*p1[i][j].x + c2*p1[i+1][j].x, 00204 c1*p1[i][j].y + c2*p1[i+1][j].y, 00205 c1*p1[i][j].z + c2*p1[i+1][j].z); 00206 vertices[1][i][j].orientation = v2 >= 0. ? RIGHT : LEFT; 00207 } 00208 else 00209 vertices[1][i][j].v = NULL; 00210 } 00211 for (i = 0; i < nx; i++) 00212 for (j = 0; j < ny - 1; j++) { 00213 gdouble v1 = f1[i][j] - iso; 00214 gdouble v2 = f1[i][j+1] - iso; 00215 if ((v1 >= 0. && v2 < 0.) || (v1 < 0. && v2 >= 0.)) { 00216 gdouble c2 = v1/(v1 - v2), c1 = 1. - c2; 00217 vertices[2][i][j].v = 00218 gts_vertex_new (klass, 00219 c1*p1[i][j].x + c2*p1[i][j+1].x, 00220 c1*p1[i][j].y + c2*p1[i][j+1].y, 00221 c1*p1[i][j].z + c2*p1[i][j+1].z); 00222 vertices[2][i][j].orientation = v2 >= 0. ? RIGHT : LEFT; 00223 } 00224 else 00225 vertices[2][i][j].v = NULL; 00226 } 00227 } 00228 00241 void gts_iso_slice_fill_cartesian (GtsIsoSlice * slice, 00242 GtsCartesianGrid g, 00243 gdouble ** f1, 00244 gdouble ** f2, 00245 gdouble iso, 00246 GtsVertexClass * klass) 00247 { 00248 OrientedVertex *** vertices; 00249 guint i, j; 00250 gdouble x, y; 00251 00252 g_return_if_fail (slice != NULL); 00253 g_return_if_fail (f1 != NULL); 00254 00255 vertices = slice->vertices; 00256 00257 if (f2) 00258 for (i = 0, x = g.x; i < g.nx; i++, x += g.dx) 00259 for (j = 0, y = g.y; j < g.ny; j++, y += g.dy) { 00260 gdouble v1 = f1[i][j] - iso; 00261 gdouble v2 = f2[i][j] - iso; 00262 if ((v1 >= 0. && v2 < 0.) || (v1 < 0. && v2 >= 0.)) { 00263 vertices[0][i][j].v = 00264 gts_vertex_new (klass, 00265 x, y, g.z + g.dz*v1/(v1 - v2)); 00266 vertices[0][i][j].orientation = v2 >= 0. ? RIGHT : LEFT; 00267 } 00268 else 00269 vertices[0][i][j].v = NULL; 00270 } 00271 for (i = 0, x = g.x; i < g.nx - 1; i++, x += g.dx) 00272 for (j = 0, y = g.y; j < g.ny; j++, y += g.dy) { 00273 gdouble v1 = f1[i][j] - iso; 00274 gdouble v2 = f1[i+1][j] - iso; 00275 if ((v1 >= 0. && v2 < 0.) || (v1 < 0. && v2 >= 0.)) { 00276 vertices[1][i][j].v = 00277 gts_vertex_new (klass, x + g.dx*v1/(v1 - v2), y, g.z); 00278 vertices[1][i][j].orientation = v2 >= 0. ? RIGHT : LEFT; 00279 } 00280 else 00281 vertices[1][i][j].v = NULL; 00282 } 00283 for (i = 0, x = g.x; i < g.nx; i++, x += g.dx) 00284 for (j = 0, y = g.y; j < g.ny - 1; j++, y += g.dy) { 00285 gdouble v1 = f1[i][j] - iso; 00286 gdouble v2 = f1[i][j+1] - iso; 00287 if ((v1 >= 0. && v2 < 0.) || (v1 < 0. && v2 >= 0.)) { 00288 vertices[2][i][j].v = 00289 gts_vertex_new (klass, x, y + g.dy*v1/(v1 - v2), g.z); 00290 vertices[2][i][j].orientation = v2 >= 0. ? RIGHT : LEFT; 00291 } 00292 else 00293 vertices[2][i][j].v = NULL; 00294 } 00295 } 00296 00303 void gts_iso_slice_destroy (GtsIsoSlice * slice) 00304 { 00305 g_return_if_fail (slice != NULL); 00306 00307 free2D ((void **) slice->vertices[0], slice->nx); 00308 free2D ((void **) slice->vertices[1], slice->nx - 1); 00309 free2D ((void **) slice->vertices[2], slice->nx); 00310 g_free (slice->vertices); 00311 g_free (slice); 00312 } 00313 00323 void gts_isosurface_slice (GtsIsoSlice * slice1, 00324 GtsIsoSlice * slice2, 00325 GtsSurface * surface) 00326 { 00327 guint j, k, l, nx, ny; 00328 OrientedVertex *** vertices[2]; 00329 GtsVertex * va[12]; 00330 00331 g_return_if_fail (slice1 != NULL); 00332 g_return_if_fail (slice2 != NULL); 00333 g_return_if_fail (surface != NULL); 00334 g_return_if_fail (slice1->nx == slice2->nx && slice1->ny == slice2->ny); 00335 00336 vertices[0] = slice1->vertices; 00337 vertices[1] = slice2->vertices; 00338 nx = slice1->nx; 00339 ny = slice1->ny; 00340 00341 /* link vertices with segments and triangles */ 00342 for (j = 0; j < nx - 1; j++) 00343 for (k = 0; k < ny - 1; k++) { 00344 gboolean cube_is_cut = FALSE; 00345 for (l = 0; l < 12; l++) { 00346 guint nv = 0, e = l; 00347 OrientedVertex ov = 00348 vertices[c[e][1]][c[e][0]][j + c[e][2]][k + c[e][3]]; 00349 while (ov.v && !GTS_OBJECT (ov.v)->reserved) { 00350 guint m = 0, * ne = edge[e][ov.orientation]; 00351 va[nv++] = ov.v; 00352 GTS_OBJECT (ov.v)->reserved = surface; 00353 ov.v = NULL; 00354 while (m < 3 && !ov.v) { 00355 e = ne[m++]; 00356 ov = vertices[c[e][1]][c[e][0]][j + c[e][2]][k + c[e][3]]; 00357 } 00358 } 00359 /* create edges and faces */ 00360 if (nv > 2) { 00361 GtsEdge * e1, * e2, * e3; 00362 guint m; 00363 if (!(e1 = GTS_EDGE (gts_vertices_are_connected (va[0], va[1])))) 00364 e1 = gts_edge_new (surface->edge_class, va[0], va[1]); 00365 for (m = 1; m < nv - 1; m++) { 00366 if (!(e2 = GTS_EDGE (gts_vertices_are_connected (va[m], va[m+1])))) 00367 e2 = gts_edge_new (surface->edge_class, va[m], va[m+1]); 00368 if (!(e3 = GTS_EDGE (gts_vertices_are_connected (va[m+1], va[0])))) 00369 e3 = gts_edge_new (surface->edge_class, va[m+1], va[0]); 00370 gts_surface_add_face (surface, 00371 gts_face_new (surface->face_class, 00372 e1, e2, e3)); 00373 e1 = e3; 00374 } 00375 } 00376 if (nv > 0) 00377 cube_is_cut = TRUE; 00378 } 00379 if (cube_is_cut) 00380 for (l = 0; l < 12; l++) { 00381 GtsVertex * v = 00382 vertices[c[l][1]][c[l][0]][j + c[l][2]][k + c[l][3]].v; 00383 if (v) 00384 GTS_OBJECT (v)->reserved = NULL; 00385 } 00386 } 00387 } 00388 00389 #define SWAP(s1, s2, tmp) (tmp = s1, s1 = s2, s2 = tmp) 00390 00407 void gts_isosurface_cartesian (GtsSurface * surface, 00408 GtsCartesianGrid g, 00409 GtsIsoCartesianFunc f, 00410 gpointer data, 00411 gdouble iso) 00412 { 00413 void * tmp; 00414 gdouble ** f1, ** f2; 00415 GtsIsoSlice * slice1, * slice2; 00416 guint i; 00417 00418 g_return_if_fail (surface != NULL); 00419 g_return_if_fail (f != NULL); 00420 g_return_if_fail (g.nx > 1); 00421 g_return_if_fail (g.ny > 1); 00422 g_return_if_fail (g.nz > 1); 00423 00424 slice1 = gts_iso_slice_new (g.nx, g.ny); 00425 slice2 = gts_iso_slice_new (g.nx, g.ny); 00426 f1 = (gdouble **) malloc2D (g.nx, g.ny, sizeof (gdouble)); 00427 f2 = (gdouble **) malloc2D (g.nx, g.ny, sizeof (gdouble)); 00428 00429 (*f) (f1, g, 0, data); 00430 g.z += g.dz; 00431 (*f) (f2, g, 1, data); 00432 g.z -= g.dz; 00433 gts_iso_slice_fill_cartesian (slice1, g, f1, f2, iso, 00434 surface->vertex_class); 00435 g.z += g.dz; 00436 for (i = 2; i < g.nz; i++) { 00437 g.z += g.dz; 00438 (*f) (f1, g, i, data); 00439 SWAP (f1, f2, tmp); 00440 g.z -= g.dz; 00441 gts_iso_slice_fill_cartesian (slice2, g, f1, f2, iso, 00442 surface->vertex_class); 00443 g.z += g.dz; 00444 gts_isosurface_slice (slice1, slice2, surface); 00445 SWAP (slice1, slice2, tmp); 00446 } 00447 gts_iso_slice_fill_cartesian (slice2, g, f2, NULL, iso, 00448 surface->vertex_class); 00449 gts_isosurface_slice (slice1, slice2, surface); 00450 00451 gts_iso_slice_destroy (slice1); 00452 gts_iso_slice_destroy (slice2); 00453 free2D ((void **) f1, g.nx); 00454 free2D ((void **) f2, g.nx); 00455 }