pcb 4.1.1
An interactive printed circuit board layout editor.

vertex.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 
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                                   &gts_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                                   &gts_color_vertex_info);
00776   }
00777 
00778   return klass;
00779 }
00780