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 gboolean gts_allow_floating_edges = FALSE; 00023 00024 static void edge_destroy (GtsObject * object) 00025 { 00026 GtsEdge * edge = GTS_EDGE (object); 00027 GSList * i; 00028 00029 i = edge->triangles; 00030 while (i) { 00031 GSList * next = i->next; 00032 gts_object_destroy (i->data); 00033 i = next; 00034 } 00035 g_assert (edge->triangles == NULL); 00036 00037 (* GTS_OBJECT_CLASS (gts_edge_class ())->parent_class->destroy) (object); 00038 } 00039 00040 static void edge_clone (GtsObject * clone, GtsObject * object) 00041 { 00042 (* GTS_OBJECT_CLASS (gts_edge_class ())->parent_class->clone) (clone, 00043 object); 00044 GTS_SEGMENT (clone)->v1 = GTS_SEGMENT (clone)->v2 = NULL; 00045 GTS_EDGE (clone)->triangles = NULL; 00046 } 00047 00048 static void edge_class_init (GtsObjectClass * klass) 00049 { 00050 klass->clone = edge_clone; 00051 klass->destroy = edge_destroy; 00052 } 00053 00054 static void edge_init (GtsEdge * edge) 00055 { 00056 edge->triangles = NULL; 00057 } 00058 00064 GtsEdgeClass * gts_edge_class (void) 00065 { 00066 static GtsEdgeClass * klass = NULL; 00067 00068 if (klass == NULL) { 00069 GtsObjectClassInfo edge_info = { 00070 "GtsEdge", 00071 sizeof (GtsEdge), 00072 sizeof (GtsEdgeClass), 00073 (GtsObjectClassInitFunc) edge_class_init, 00074 (GtsObjectInitFunc) edge_init, 00075 (GtsArgSetFunc) NULL, 00076 (GtsArgGetFunc) NULL 00077 }; 00078 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_segment_class ()), 00079 &edge_info); 00080 } 00081 00082 return klass; 00083 } 00084 00093 GtsEdge * gts_edge_new (GtsEdgeClass * klass, 00094 GtsVertex * v1, GtsVertex * v2) 00095 { 00096 return GTS_EDGE (gts_segment_new (GTS_SEGMENT_CLASS (klass), v1, v2)); 00097 } 00098 00099 void gts_edge_remove(GtsEdge *edge) 00100 { 00101 edge->segment.v1->segments = g_slist_remove(edge->segment.v1->segments, &edge->segment); 00102 edge->segment.v2->segments = g_slist_remove(edge->segment.v2->segments, &edge->segment); 00103 edge_destroy(GTS_OBJECT (edge)); 00104 } 00105 00116 void gts_edge_replace (GtsEdge * e, GtsEdge * with) 00117 { 00118 GSList * i; 00119 00120 g_return_if_fail (e != NULL && with != NULL && e != with); 00121 00122 i = e->triangles; 00123 while (i) { 00124 GtsTriangle * t = i->data; 00125 if (t->e1 == e) t->e1 = with; 00126 if (t->e2 == e) t->e2 = with; 00127 if (t->e3 == e) t->e3 = with; 00128 if (!g_slist_find (with->triangles, t)) 00129 with->triangles = g_slist_prepend (with->triangles, t); 00130 i = i->next; 00131 } 00132 g_slist_free (e->triangles); 00133 e->triangles = NULL; 00134 } 00135 00143 GtsFace * gts_edge_has_parent_surface (GtsEdge * e, GtsSurface * surface) 00144 { 00145 GSList * i; 00146 00147 g_return_val_if_fail (e != NULL, NULL); 00148 00149 i = e->triangles; 00150 while (i) { 00151 if (GTS_IS_FACE (i->data) && 00152 gts_face_has_parent_surface (i->data, surface)) 00153 return i->data; 00154 i = i->next; 00155 } 00156 return NULL; 00157 } 00158 00167 GtsFace * gts_edge_has_any_parent_surface (GtsEdge * e) 00168 { 00169 GSList * i; 00170 00171 g_return_val_if_fail (e != NULL, NULL); 00172 00173 i = e->triangles; 00174 while (i) { 00175 GtsTriangle * t = i->data; 00176 if (GTS_IS_FACE (t) && GTS_FACE (t)->surfaces != NULL) 00177 return GTS_FACE (t); 00178 i = i->next; 00179 } 00180 return NULL; 00181 } 00182 00193 GtsFace * gts_edge_is_boundary (GtsEdge * e, GtsSurface * surface) 00194 { 00195 GSList * i; 00196 GtsFace * f = NULL; 00197 00198 g_return_val_if_fail (e != NULL, NULL); 00199 00200 i = e->triangles; 00201 while (i) { 00202 if (GTS_IS_FACE (i->data)) { 00203 if (!surface || gts_face_has_parent_surface (i->data, surface)) { 00204 if (f != NULL) 00205 return NULL; 00206 f = i->data; 00207 } 00208 } 00209 i = i->next; 00210 } 00211 return f; 00212 } 00213 00222 GSList * gts_edges_from_vertices (GSList * vertices, GtsSurface * parent) 00223 { 00224 GHashTable * hash; 00225 GSList * edges = NULL, * i; 00226 00227 g_return_val_if_fail (parent != NULL, NULL); 00228 00229 hash = g_hash_table_new (NULL, NULL); 00230 i = vertices; 00231 while (i) { 00232 GSList * j = GTS_VERTEX (i->data)->segments; 00233 while (j) { 00234 GtsSegment * s = j->data; 00235 if (GTS_IS_EDGE (s) && 00236 gts_edge_has_parent_surface (GTS_EDGE (s), parent) && 00237 g_hash_table_lookup (hash, s) == NULL) { 00238 edges = g_slist_prepend (edges, s); 00239 g_hash_table_insert (hash, s, i); 00240 } 00241 j = j->next; 00242 } 00243 i = i->next; 00244 } 00245 g_hash_table_destroy (hash); 00246 return edges; 00247 } 00248 00256 guint gts_edge_face_number (GtsEdge * e, GtsSurface * s) 00257 { 00258 GSList * i; 00259 guint nt = 0; 00260 00261 g_return_val_if_fail (e != NULL, 0); 00262 g_return_val_if_fail (s != NULL, 0); 00263 00264 i = e->triangles; 00265 while (i) { 00266 if (GTS_IS_FACE (i->data) && 00267 gts_face_has_parent_surface (GTS_FACE (i->data), s)) 00268 nt++; 00269 i = i->next; 00270 } 00271 return nt; 00272 } 00273 00281 GtsEdge * gts_edge_is_duplicate (GtsEdge * e) 00282 { 00283 GSList * i; 00284 GtsVertex * v2; 00285 00286 g_return_val_if_fail (e != NULL, NULL); 00287 00288 v2 = GTS_SEGMENT (e)->v2; 00289 i = GTS_SEGMENT (e)->v1->segments; 00290 if (GTS_SEGMENT (e)->v1 == v2) /* e is degenerate: special treatment */ 00291 while (i) { 00292 GtsSegment * s = i->data; 00293 if (s != GTS_SEGMENT (e) && 00294 GTS_IS_EDGE (s) && 00295 s->v1 == v2 && s->v2 == v2) 00296 return GTS_EDGE (s); 00297 i = i->next; 00298 } 00299 else /* e is not degenerate */ 00300 while (i) { 00301 GtsSegment * s = i->data; 00302 if (s != GTS_SEGMENT (e) && 00303 GTS_IS_EDGE (s) && 00304 (s->v1 == v2 || s->v2 == v2)) 00305 return GTS_EDGE (s); 00306 i = i->next; 00307 } 00308 return NULL; 00309 } 00310 00321 GList * gts_edges_merge (GList * edges) 00322 { 00323 GList * i = edges; 00324 00325 /* we want to control edge destruction */ 00326 gts_allow_floating_edges = TRUE; 00327 while (i) { 00328 GtsEdge * e = i->data; 00329 GtsEdge * de = gts_edge_is_duplicate (e); 00330 if (de) { 00331 GList * next = i->next; 00332 edges = g_list_remove_link (edges, i); 00333 g_list_free_1 (i); 00334 i = next; 00335 gts_edge_replace (e, de); 00336 gts_object_destroy (GTS_OBJECT (e)); 00337 } 00338 else 00339 i = i->next; 00340 } 00341 gts_allow_floating_edges = FALSE;; 00342 00343 return edges; 00344 } 00345 00346 static void triangle_vertices_edges (GtsTriangle * t, 00347 GtsEdge * e, 00348 GtsVertex ** v, 00349 GtsEdge ** ee1, 00350 GtsEdge ** ee2) 00351 { 00352 GtsEdge * e1 = t->e1, * e2 = t->e2, * e3 = t->e3; 00353 GtsVertex * v1 = GTS_SEGMENT (e)->v1; 00354 00355 if (e1 == e) e1 = e3; 00356 else if (e2 == e) e2 = e3; 00357 else g_assert (e3 == e); 00358 00359 if (GTS_SEGMENT (e2)->v1 == v1 || GTS_SEGMENT (e2)->v2 == v1) { 00360 e3 = e1; e1 = e2; e2 = e3; 00361 } 00362 if (GTS_SEGMENT (e1)->v1 == v1) 00363 *v = GTS_SEGMENT (e1)->v2; 00364 else 00365 *v = GTS_SEGMENT (e1)->v1; 00366 *ee1 = e1; 00367 *ee2 = e2; 00368 } 00369 00377 gboolean gts_edge_belongs_to_tetrahedron (GtsEdge * e) 00378 { 00379 GSList * i; 00380 00381 g_return_val_if_fail (e != NULL, FALSE); 00382 00383 i = e->triangles; 00384 while (i) { 00385 GtsEdge * e1, * e2; 00386 GtsVertex * vt1; 00387 GSList * j = i->next; 00388 triangle_vertices_edges (i->data, e, &vt1, &e1, &e2); 00389 while (j) { 00390 GtsSegment * s5; 00391 GtsEdge * e3, * e4; 00392 GtsVertex * vt2; 00393 00394 triangle_vertices_edges (j->data, e, &vt2, &e3, &e4); 00395 s5 = gts_vertices_are_connected (vt1, vt2); 00396 if (GTS_IS_EDGE (s5) && 00397 gts_triangle_use_edges (e1, e3, GTS_EDGE (s5)) && 00398 gts_triangle_use_edges (e2, e4, GTS_EDGE (s5))) 00399 return TRUE; 00400 j = j->next; 00401 } 00402 i = i->next; 00403 } 00404 00405 return FALSE; 00406 } 00407 00408 #define edge_use_vertex(e, v) (GTS_SEGMENT(e)->v1 == v ||\ 00409 GTS_SEGMENT(e)->v2 == v) 00410 00411 static GtsEdge * next_edge (GtsTriangle * t, 00412 GtsEdge * e1, 00413 GtsEdge * e) 00414 { 00415 GtsVertex * v1 = GTS_SEGMENT (e)->v1; 00416 GtsVertex * v2 = GTS_SEGMENT (e)->v2; 00417 00418 if (t->e1 != e1 && t->e1 != e && 00419 (edge_use_vertex (t->e1, v1) || edge_use_vertex (t->e1, v2))) 00420 return t->e1; 00421 else if (t->e2 != e1 && t->e2 != e && 00422 (edge_use_vertex (t->e2, v1) || edge_use_vertex (t->e2, v2))) 00423 return t->e2; 00424 else if (t->e3 != e1 && t->e3 != e && 00425 (edge_use_vertex (t->e3, v1) || edge_use_vertex (t->e3, v2))) 00426 return t->e3; 00427 g_assert_not_reached (); 00428 return NULL; 00429 } 00430 00431 static void triangle_next (GtsEdge * e1, GtsEdge * e) 00432 { 00433 GSList * i; 00434 00435 i = e1->triangles; 00436 while (i) { 00437 GtsTriangle * t = i->data; 00438 if (GTS_OBJECT (t)->reserved) { 00439 GTS_OBJECT (t)->reserved = NULL; 00440 triangle_next (next_edge (t, e1, e), e); 00441 } 00442 i = i->next; 00443 } 00444 } 00445 00453 guint gts_edge_is_contact (GtsEdge * e) 00454 { 00455 GSList * i, * triangles; 00456 guint ncomponent = 0; 00457 00458 g_return_val_if_fail (e != NULL, 0); 00459 00460 triangles = gts_vertex_triangles (GTS_SEGMENT (e)->v1, NULL); 00461 i = triangles = gts_vertex_triangles (GTS_SEGMENT (e)->v2, triangles); 00462 while (i) { 00463 GTS_OBJECT (i->data)->reserved = i; 00464 i = i->next; 00465 } 00466 00467 i = e->triangles; 00468 while (i) { 00469 GtsTriangle * t = i->data; 00470 if (GTS_OBJECT (t)->reserved) { 00471 GtsEdge * e1; 00472 GTS_OBJECT (t)->reserved = NULL; 00473 e1 = next_edge (t, NULL, e); 00474 triangle_next (e1, e); 00475 triangle_next (next_edge (t, e1, e), e); 00476 ncomponent++; 00477 } 00478 i = i->next; 00479 } 00480 00481 g_slist_foreach (triangles, (GFunc) gts_object_reset_reserved, NULL); 00482 g_slist_free (triangles); 00483 00484 return ncomponent; 00485 } 00486 00495 void gts_edge_swap (GtsEdge * e, GtsSurface * s) 00496 { 00497 GtsTriangle * t1 = NULL, * t2 = NULL, * t; 00498 GtsFace * f; 00499 GSList * i; 00500 GtsVertex * v1, * v2, * v3, * v4, * v5, * v6; 00501 GtsEdge * e1, * e2, * e3, * e4; 00502 GtsSegment * v3v6; 00503 00504 g_return_if_fail (e != NULL); 00505 g_return_if_fail (s != NULL); 00506 00507 i = e->triangles; 00508 while (i) { 00509 if (GTS_IS_FACE (i->data) && gts_face_has_parent_surface (i->data, s)) { 00510 if (!t1) 00511 t1 = i->data; 00512 else if (!t2) 00513 t2 = i->data; 00514 else 00515 g_return_if_fail (gts_edge_face_number (e, s) == 2); 00516 } 00517 i = i->next; 00518 } 00519 g_assert (t1 && t2); 00520 00521 gts_triangle_vertices_edges (t1, e, &v1, &v2, &v3, &e, &e1, &e2); 00522 gts_triangle_vertices_edges (t2, e, &v4, &v5, &v6, &e, &e3, &e4); 00523 g_assert (v2 == v4 && v1 == v5); 00524 00525 v3v6 = gts_vertices_are_connected (v3, v6); 00526 if (!GTS_IS_EDGE (v3v6)) 00527 v3v6 = GTS_SEGMENT (gts_edge_new (s->edge_class, v3, v6)); 00528 f = gts_face_new (s->face_class, e1, GTS_EDGE (v3v6), e4); 00529 if ((t = gts_triangle_is_duplicate (GTS_TRIANGLE (f))) && 00530 GTS_IS_FACE (t)) { 00531 gts_object_destroy (GTS_OBJECT (f)); 00532 f = GTS_FACE (t); 00533 } 00534 gts_surface_add_face (s, f); 00535 00536 f = gts_face_new (s->face_class, GTS_EDGE (v3v6), e2, e3); 00537 if ((t = gts_triangle_is_duplicate (GTS_TRIANGLE (f))) && 00538 GTS_IS_FACE (t)) { 00539 gts_object_destroy (GTS_OBJECT (f)); 00540 f = GTS_FACE (t); 00541 } 00542 gts_surface_add_face (s, f); 00543 00544 gts_surface_remove_face (s, GTS_FACE (t1)); 00545 gts_surface_remove_face (s, GTS_FACE (t2)); 00546 } 00547 00560 gboolean gts_edge_manifold_faces (GtsEdge * e, GtsSurface * s, 00561 GtsFace ** f1, GtsFace ** f2) 00562 { 00563 GSList * i; 00564 00565 g_return_val_if_fail (e != NULL, FALSE); 00566 g_return_val_if_fail (s != NULL, FALSE); 00567 g_return_val_if_fail (f1 != NULL, FALSE); 00568 g_return_val_if_fail (f2 != NULL, FALSE); 00569 00570 *f1 = *f2 = NULL; 00571 i = e->triangles; 00572 while (i) { 00573 if (GTS_IS_FACE (i->data) && gts_face_has_parent_surface (i->data, s)) { 00574 if (!(*f1)) *f1 = i->data; 00575 else if (!(*f2)) *f2 = i->data; 00576 else return FALSE; 00577 } 00578 i = i->next; 00579 } 00580 00581 return (*f1 && *f2); 00582 }