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 00023 gboolean gts_allow_floating_vertices = FALSE; 00024 00025 static void vertex_destroy (GtsObject * object) 00026 { 00027 GtsVertex * vertex = GTS_VERTEX (object); 00028 GSList * i; 00029 00030 i = vertex->segments; 00031 while (i) { 00032 GTS_OBJECT_SET_FLAGS (i->data, GTS_DESTROYED); 00033 i = i->next; 00034 } 00035 i = vertex->segments; 00036 while (i) { 00037 GSList * next = i->next; 00038 gts_object_destroy (i->data); 00039 i = next; 00040 } 00041 g_assert (vertex->segments == NULL); 00042 00043 (* GTS_OBJECT_CLASS (gts_vertex_class ())->parent_class->destroy) (object); 00044 } 00045 00046 static void vertex_clone (GtsObject * clone, GtsObject * object) 00047 { 00048 (* GTS_OBJECT_CLASS (gts_vertex_class ())->parent_class->clone) (clone, 00049 object); 00050 GTS_VERTEX (clone)->segments = NULL; 00051 } 00052 00053 static void vertex_class_init (GtsVertexClass * klass) 00054 { 00055 klass->intersection_attributes = NULL; 00056 GTS_OBJECT_CLASS (klass)->clone = vertex_clone; 00057 GTS_OBJECT_CLASS (klass)->destroy = vertex_destroy; 00058 } 00059 00060 static void vertex_init (GtsVertex * vertex) 00061 { 00062 vertex->segments = NULL; 00063 } 00064 00070 GtsVertexClass * gts_vertex_class (void) 00071 { 00072 static GtsVertexClass * klass = NULL; 00073 00074 if (klass == NULL) { 00075 GtsObjectClassInfo vertex_info = { 00076 "GtsVertex", 00077 sizeof (GtsVertex), 00078 sizeof (GtsVertexClass), 00079 (GtsObjectClassInitFunc) vertex_class_init, 00080 (GtsObjectInitFunc) vertex_init, 00081 (GtsArgSetFunc) NULL, 00082 (GtsArgGetFunc) NULL 00083 }; 00084 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_point_class ()), 00085 &vertex_info); 00086 } 00087 00088 return klass; 00089 } 00090 00100 GtsVertex * gts_vertex_new (GtsVertexClass * klass, 00101 gdouble x, gdouble y, gdouble z) 00102 { 00103 GtsVertex * v; 00104 00105 v = GTS_VERTEX (gts_object_new (GTS_OBJECT_CLASS (klass))); 00106 gts_point_set (GTS_POINT (v), x, y, z); 00107 00108 return v; 00109 } 00110 00121 void gts_vertex_replace (GtsVertex * v, GtsVertex * with) 00122 { 00123 GSList * i; 00124 00125 g_return_if_fail (v != NULL); 00126 g_return_if_fail (with != NULL); 00127 g_return_if_fail (v != with); 00128 00129 i = v->segments; 00130 while (i) { 00131 GtsSegment * s = i->data; 00132 if (s->v1 != with && s->v2 != with) 00133 with->segments = g_slist_prepend (with->segments, s); 00134 if (s->v1 == v) s->v1 = with; 00135 if (s->v2 == v) s->v2 = with; 00136 i = i->next; 00137 } 00138 g_slist_free (v->segments); 00139 v->segments = NULL; 00140 } 00141 00149 gboolean gts_vertex_is_unattached (GtsVertex * v) 00150 { 00151 g_return_val_if_fail (v != NULL, FALSE); 00152 if (v->segments == NULL) 00153 return TRUE; 00154 return FALSE; 00155 } 00156 00165 GtsSegment * gts_vertices_are_connected (GtsVertex * v1, GtsVertex * v2) 00166 { 00167 GSList * i; 00168 00169 g_return_val_if_fail (v1 != NULL, FALSE); 00170 g_return_val_if_fail (v2 != NULL, FALSE); 00171 00172 i = v1->segments; 00173 while (i) { 00174 GtsSegment * s = i->data; 00175 00176 if (s->v1 == v2 || s->v2 == v2) 00177 return s; 00178 i = i->next; 00179 } 00180 return NULL; 00181 } 00182 00190 GSList * gts_vertices_from_segments (GSList * segments) 00191 { 00192 GHashTable * hash; 00193 GSList * vertices = NULL, * i; 00194 00195 hash = g_hash_table_new (NULL, NULL); 00196 i = segments; 00197 while (i) { 00198 GtsSegment * s = i->data; 00199 if (g_hash_table_lookup (hash, s->v1) == NULL) { 00200 vertices = g_slist_prepend (vertices, s->v1); 00201 g_hash_table_insert (hash, s->v1, s); 00202 } 00203 if (g_hash_table_lookup (hash, s->v2) == NULL) { 00204 vertices = g_slist_prepend (vertices, s->v2); 00205 g_hash_table_insert (hash, s->v2, s); 00206 } 00207 i = i->next; 00208 } 00209 g_hash_table_destroy (hash); 00210 return vertices; 00211 } 00212 00224 GSList * gts_vertex_triangles (GtsVertex * v, 00225 GSList * list) 00226 { 00227 GSList * i; 00228 00229 g_return_val_if_fail (v != NULL, NULL); 00230 00231 i = v->segments; 00232 while (i) { 00233 GtsSegment * s = i->data; 00234 if (GTS_IS_EDGE (s)) { 00235 GSList * j = GTS_EDGE (s)->triangles; 00236 while (j) { 00237 if (!g_slist_find (list, j->data)) 00238 list = g_slist_prepend (list, j->data); 00239 j = j->next; 00240 } 00241 } 00242 i = i->next; 00243 } 00244 return list; 00245 } 00246 00259 GSList * gts_vertex_faces (GtsVertex * v, 00260 GtsSurface * surface, 00261 GSList * list) 00262 { 00263 GSList * i; 00264 00265 g_return_val_if_fail (v != NULL, NULL); 00266 00267 i = v->segments; 00268 while (i) { 00269 GtsSegment * s = i->data; 00270 if (GTS_IS_EDGE (s)) { 00271 GSList * j = GTS_EDGE (s)->triangles; 00272 while (j) { 00273 GtsTriangle * t = j->data; 00274 if (GTS_IS_FACE (t) 00275 && 00276 (!surface || gts_face_has_parent_surface (GTS_FACE (t), surface)) 00277 && 00278 !g_slist_find (list, t)) 00279 list = g_slist_prepend (list, t); 00280 j = j->next; 00281 } 00282 } 00283 i = i->next; 00284 } 00285 return list; 00286 } 00287 00300 GSList * gts_vertex_neighbors (GtsVertex * v, 00301 GSList * list, 00302 GtsSurface * surface) 00303 { 00304 GSList * i; 00305 00306 g_return_val_if_fail (v != NULL, NULL); 00307 00308 i = v->segments; 00309 while (i) { 00310 GtsSegment * s = i->data; 00311 GtsVertex * v1 = s->v1 == v ? s->v2 : s->v1; 00312 if (v1 != v && 00313 (!surface || 00314 (GTS_IS_EDGE (s) && 00315 gts_edge_has_parent_surface (GTS_EDGE (s), surface))) && 00316 !g_slist_find (list, v1)) 00317 list = g_slist_prepend (list, v1); 00318 i = i->next; 00319 } 00320 return list; 00321 } 00322 00331 gboolean gts_vertex_is_boundary (GtsVertex * v, GtsSurface * surface) 00332 { 00333 GSList * i; 00334 00335 g_return_val_if_fail (v != NULL, FALSE); 00336 00337 i = v->segments; 00338 while (i) { 00339 if (GTS_IS_EDGE (i->data) && 00340 gts_edge_is_boundary (i->data, surface)) 00341 return TRUE; 00342 i = i->next; 00343 } 00344 00345 return FALSE; 00346 } 00347 00363 GList * gts_vertices_merge (GList * vertices, 00364 gdouble epsilon, 00365 gboolean (* check) (GtsVertex *, GtsVertex *)) 00366 { 00367 GPtrArray * array; 00368 GList * i; 00369 GNode * kdtree; 00370 00371 g_return_val_if_fail (vertices != NULL, 0); 00372 00373 array = g_ptr_array_new (); 00374 i = vertices; 00375 while (i) { 00376 g_ptr_array_add (array, i->data); 00377 i = i->next; 00378 } 00379 kdtree = gts_kdtree_new (array, NULL); 00380 g_ptr_array_free (array, TRUE); 00381 00382 i = vertices; 00383 while (i) { 00384 GtsVertex * v = i->data; 00385 if (!GTS_OBJECT (v)->reserved) { /* Do something only if v is active */ 00386 GtsBBox * bbox; 00387 GSList * selected, * j; 00388 00389 /* build bounding box */ 00390 bbox = gts_bbox_new (gts_bbox_class (), 00391 v, 00392 GTS_POINT (v)->x - epsilon, 00393 GTS_POINT (v)->y - epsilon, 00394 GTS_POINT (v)->z - epsilon, 00395 GTS_POINT (v)->x + epsilon, 00396 GTS_POINT (v)->y + epsilon, 00397 GTS_POINT (v)->z + epsilon); 00398 00399 /* select vertices which are inside bbox using kdtree */ 00400 j = selected = gts_kdtree_range (kdtree, bbox, NULL); 00401 while (j) { 00402 GtsVertex * sv = j->data; 00403 if (sv != v && !GTS_OBJECT (sv)->reserved && (!check || (*check) (sv, v))) { 00404 /* sv is not v and is active */ 00405 gts_vertex_replace (sv, v); 00406 GTS_OBJECT (sv)->reserved = sv; /* mark sv as inactive */ 00407 } 00408 j = j->next; 00409 } 00410 g_slist_free (selected); 00411 gts_object_destroy (GTS_OBJECT (bbox)); 00412 } 00413 i = i->next; 00414 } 00415 00416 gts_kdtree_destroy (kdtree); 00417 00418 /* destroy inactive vertices and removes them from list */ 00419 00420 /* we want to control vertex destruction */ 00421 gts_allow_floating_vertices = TRUE; 00422 00423 i = vertices; 00424 while (i) { 00425 GtsVertex * v = i->data; 00426 GList * next = i->next; 00427 if (GTS_OBJECT (v)->reserved) { /* v is inactive */ 00428 gts_object_destroy (GTS_OBJECT (v)); 00429 vertices = g_list_remove_link (vertices, i); 00430 g_list_free_1 (i); 00431 } 00432 i = next; 00433 } 00434 gts_allow_floating_vertices = FALSE; 00435 00436 return vertices; 00437 } 00438 00439 /* returns the list of edges belonging to @surface turning around @v */ 00440 static GSList * edge_fan_list (GtsVertex * v, 00441 GtsSurface * surface, 00442 GtsFace * f, 00443 GtsEdge * e, 00444 GtsFace * first) 00445 { 00446 GSList * i = e->triangles; 00447 GtsFace * neighbor = NULL; 00448 GtsEdge * next = NULL, * enext = NULL; 00449 00450 while (i) { 00451 GtsFace * f1 = i->data; 00452 if (GTS_IS_FACE (f1) && 00453 f1 != f && 00454 gts_face_has_parent_surface (f1, surface)) { 00455 g_return_val_if_fail (neighbor == NULL, NULL); /* non-manifold edge */ 00456 neighbor = f1; 00457 } 00458 i = i->next; 00459 } 00460 if (neighbor == NULL || neighbor == first) /* end of fan */ 00461 return NULL; 00462 00463 if (GTS_TRIANGLE (neighbor)->e1 == e) { 00464 next = GTS_TRIANGLE (neighbor)->e2; 00465 enext = GTS_TRIANGLE (neighbor)->e3; 00466 } 00467 else if (GTS_TRIANGLE (neighbor)->e2 == e) { 00468 next = GTS_TRIANGLE (neighbor)->e3; 00469 enext = GTS_TRIANGLE (neighbor)->e1; 00470 } 00471 else if (GTS_TRIANGLE (neighbor)->e3 == e) { 00472 next = GTS_TRIANGLE (neighbor)->e1; 00473 enext = GTS_TRIANGLE (neighbor)->e2; 00474 } 00475 else 00476 g_assert_not_reached (); 00477 00478 /* checking for correct orientation */ 00479 g_return_val_if_fail (GTS_SEGMENT (enext)->v1 == v || 00480 GTS_SEGMENT (enext)->v2 == v, NULL); 00481 00482 return g_slist_prepend (edge_fan_list (v, surface, neighbor, enext, first), 00483 next); 00484 } 00485 00495 GSList * gts_vertex_fan_oriented (GtsVertex * v, GtsSurface * surface) 00496 { 00497 GtsFace * f = NULL; 00498 guint d = 2; 00499 GSList * i; 00500 GtsVertex * v1, * v2, * v3; 00501 GtsEdge * e1, * e2, * e3; 00502 00503 g_return_val_if_fail (v != NULL, NULL); 00504 g_return_val_if_fail (surface != NULL, NULL); 00505 00506 i = v->segments; 00507 while (i) { 00508 GtsEdge * e = i->data; 00509 if (GTS_IS_EDGE (e)) { 00510 GSList * j = e->triangles; 00511 GtsFace * f1 = NULL; 00512 guint degree = 0; 00513 while (j) { 00514 if (GTS_IS_FACE (j->data) && 00515 gts_face_has_parent_surface (j->data, surface)) { 00516 f1 = j->data; 00517 degree++; 00518 } 00519 j = j->next; 00520 } 00521 if (f1 != NULL) { 00522 g_return_val_if_fail (degree <= 2, NULL); /* non-manifold edge */ 00523 if (degree == 1) { 00524 gts_triangle_vertices_edges (GTS_TRIANGLE (f1), NULL, 00525 &v1, &v2, &v3, &e1, &e2, &e3); 00526 if (v == v2) { 00527 e2 = e3; 00528 e3 = e1; 00529 } 00530 else if (v == v3) { 00531 e3 = e2; 00532 e2 = e1; 00533 } 00534 if (e3 != e) { 00535 d = 1; 00536 f = f1; 00537 } 00538 } 00539 else if (degree <= d) 00540 f = f1; 00541 } 00542 } 00543 i = i->next; 00544 } 00545 00546 if (f == NULL) 00547 return NULL; 00548 00549 gts_triangle_vertices_edges (GTS_TRIANGLE (f), NULL, 00550 &v1, &v2, &v3, &e1, &e2, &e3); 00551 if (v == v2) { 00552 e2 = e3; 00553 e3 = e1; 00554 } 00555 else if (v == v3) { 00556 e3 = e2; 00557 e2 = e1; 00558 } 00559 00560 return g_slist_prepend (edge_fan_list (v, surface, f, e3, f), e2); 00561 } 00562 00563 #define edge_use_vertex(e, v) (GTS_SEGMENT(e)->v1 == v ||\ 00564 GTS_SEGMENT(e)->v2 == v) 00565 00566 static GtsEdge * replace_vertex (GtsTriangle * t, 00567 GtsEdge * e1, 00568 GtsVertex * v, 00569 GtsVertex * with) 00570 { 00571 GtsEdge * e = NULL; 00572 00573 if (t->e1 != e1 && edge_use_vertex (t->e1, v)) 00574 e = t->e1; 00575 else if (t->e2 != e1 && edge_use_vertex (t->e2, v)) 00576 e = t->e2; 00577 else if (t->e3 != e1 && edge_use_vertex (t->e3, v)) 00578 e = t->e3; 00579 else 00580 return NULL; 00581 00582 if (with != v) { 00583 GtsSegment * s = GTS_SEGMENT (e); 00584 if (s->v1 == v) s->v1 = with; 00585 if (s->v2 == v) s->v2 = with; 00586 with->segments = g_slist_prepend (with->segments, s); 00587 v->segments = g_slist_remove (v->segments, s); 00588 } 00589 00590 return e; 00591 } 00592 00593 static void triangle_next (GtsEdge * e, GtsVertex * v, GtsVertex * with) 00594 { 00595 GSList * i; 00596 00597 if (e == NULL) 00598 return; 00599 00600 i = e->triangles; 00601 while (i) { 00602 GtsTriangle * t = i->data; 00603 if (GTS_OBJECT (t)->reserved) { 00604 GTS_OBJECT (t)->reserved = NULL; 00605 triangle_next (replace_vertex (t, e, v, with), v, with); 00606 } 00607 i = i->next; 00608 } 00609 } 00610 00621 guint gts_vertex_is_contact (GtsVertex * v, gboolean sever) 00622 { 00623 GSList * triangles, * i; 00624 GtsVertex * with = v; 00625 guint ncomponent = 0; 00626 00627 g_return_val_if_fail (v != NULL, 0); 00628 00629 triangles = gts_vertex_triangles (v, NULL); 00630 i = triangles; 00631 while (i) { 00632 GTS_OBJECT (i->data)->reserved = i; 00633 i = i->next; 00634 } 00635 00636 i = triangles; 00637 while (i) { 00638 GtsTriangle * t = i->data; 00639 if (GTS_OBJECT (t)->reserved) { 00640 GtsEdge * e; 00641 if (ncomponent && sever) 00642 with = GTS_VERTEX (gts_object_clone (GTS_OBJECT (v))); 00643 GTS_OBJECT (t)->reserved = NULL; 00644 e = replace_vertex (t, NULL, v, with); 00645 triangle_next (e, v, with); 00646 triangle_next (replace_vertex (t, e, v, with), v, with); 00647 ncomponent++; 00648 } 00649 i = i->next; 00650 } 00651 g_slist_free (triangles); 00652 00653 return ncomponent; 00654 } 00655 00656 /* GtsVertexNormal: Object */ 00657 00658 static void vertex_normal_attributes (GtsVertex * v, 00659 GtsObject * e, 00660 GtsObject * t) 00661 { 00662 g_return_if_fail (GTS_IS_EDGE (e)); 00663 g_return_if_fail (GTS_IS_TRIANGLE (t)); 00664 00665 if (GTS_IS_VERTEX_NORMAL (GTS_SEGMENT (e)->v1) && 00666 GTS_IS_VERTEX_NORMAL (GTS_SEGMENT (e)->v2)) { 00667 GtsPoint * p1 = GTS_POINT (GTS_SEGMENT (e)->v1); 00668 GtsPoint * p2 = GTS_POINT (GTS_SEGMENT (e)->v2); 00669 GtsPoint * p = GTS_POINT (v); 00670 gdouble a, b, lambda; 00671 guint i; 00672 00673 a = p2->x - p1->x; b = p->x - p1->x; 00674 if (fabs (p2->y - p1->y) > fabs (a)) { 00675 a = p2->y - p1->y; b = p->y - p1->y; 00676 } 00677 if (fabs (p2->z - p1->z) > fabs (a)) { 00678 a = p2->z - p1->z; b = p->z - p1->z; 00679 } 00680 lambda = a != 0. ? b/a : 0.; 00681 for (i = 0; i < 3; i++) 00682 GTS_VERTEX_NORMAL (v)->n[i] = 00683 (1. - lambda)*GTS_VERTEX_NORMAL (GTS_SEGMENT (e)->v1)->n[i] + 00684 lambda*GTS_VERTEX_NORMAL (GTS_SEGMENT (e)->v2)->n[i]; 00685 } 00686 else { 00687 GtsVertex * v1, * v2, * v3; 00688 00689 gts_triangle_vertices (GTS_TRIANGLE (t), &v1, &v2, &v3); 00690 if (GTS_IS_VERTEX_NORMAL (v1) && 00691 GTS_IS_VERTEX_NORMAL (v2) && 00692 GTS_IS_VERTEX_NORMAL (v3)) { 00693 GtsVector a1, a2, a3, det; 00694 guint i, j = 0; 00695 gdouble l1, l2; 00696 00697 gts_vector_init (a1, GTS_POINT (v1), GTS_POINT (v)); 00698 gts_vector_init (a2, GTS_POINT (v1), GTS_POINT (v2)); 00699 gts_vector_init (a3, GTS_POINT (v1), GTS_POINT (v3)); 00700 gts_vector_cross (det, a2, a3); 00701 if (fabs (det[1]) > fabs (det[0])) j = 1; 00702 if (fabs (det[2]) > fabs (det[j])) j = 2; 00703 if (det[j] == 0.) { 00704 g_warning ("vertex_normal_attributes: det[%d] == 0.", j); 00705 return; 00706 } 00707 switch (j) { 00708 case 0: 00709 l1 = (a1[1]*a3[2] - a1[2]*a3[1])/det[0]; 00710 l2 = (a1[2]*a2[1] - a1[1]*a2[2])/det[0]; 00711 break; 00712 case 1: 00713 l1 = (a1[2]*a3[0] - a1[0]*a3[2])/det[1]; 00714 l2 = (a1[0]*a2[2] - a1[2]*a2[0])/det[1]; 00715 break; 00716 case 2: 00717 l1 = (a1[0]*a3[1] - a1[1]*a3[0])/det[2]; 00718 l2 = (a1[1]*a2[0] - a1[0]*a2[1])/det[2]; 00719 break; 00720 default: 00721 l1 = l2 = 0.; 00722 } 00723 for (i = 0; i < 3; i++) 00724 GTS_VERTEX_NORMAL (v)->n[i] = 00725 GTS_VERTEX_NORMAL (v1)->n[i]*(1. - l1 - l2) + 00726 GTS_VERTEX_NORMAL (v2)->n[i]*l1 + 00727 GTS_VERTEX_NORMAL (v3)->n[i]*l2; 00728 } 00729 } 00730 } 00731 00732 static void gts_vertex_normal_class_init (GtsVertexClass * klass) 00733 { 00734 klass->intersection_attributes = vertex_normal_attributes; 00735 } 00736 00737 GtsVertexClass * gts_vertex_normal_class (void) 00738 { 00739 static GtsVertexClass * klass = NULL; 00740 00741 if (klass == NULL) { 00742 GtsObjectClassInfo gts_vertex_normal_info = { 00743 "GtsVertexNormal", 00744 sizeof (GtsVertexNormal), 00745 sizeof (GtsVertexClass), 00746 (GtsObjectClassInitFunc) gts_vertex_normal_class_init, 00747 (GtsObjectInitFunc) NULL, 00748 (GtsArgSetFunc) NULL, 00749 (GtsArgGetFunc) NULL 00750 }; 00751 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_vertex_class ()), 00752 >s_vertex_normal_info); 00753 } 00754 00755 return klass; 00756 } 00757 00758 /* GtsColorVertex: Object */ 00759 00760 GtsVertexClass * gts_color_vertex_class (void) 00761 { 00762 static GtsVertexClass * klass = NULL; 00763 00764 if (klass == NULL) { 00765 GtsObjectClassInfo gts_color_vertex_info = { 00766 "GtsColorVertex", 00767 sizeof (GtsColorVertex), 00768 sizeof (GtsVertexClass), 00769 (GtsObjectClassInitFunc) NULL, 00770 (GtsObjectInitFunc) NULL, 00771 (GtsArgSetFunc) NULL, 00772 (GtsArgGetFunc) NULL 00773 }; 00774 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_vertex_class ()), 00775 >s_color_vertex_info); 00776 } 00777 00778 return klass; 00779 } 00780