pcb 4.1.1
An interactive printed circuit board layout editor.

face.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 "gts.h"
00021 
00022 gboolean gts_allow_floating_faces = FALSE;
00023 
00024 static void face_destroy (GtsObject * object)
00025 {
00026   GtsFace * face = GTS_FACE (object);
00027   GSList * i;
00028 
00029   i = face->surfaces;
00030   while (i) {
00031     GSList * next = i->next;
00032     gts_surface_remove_face (i->data, face);
00033     i = next;
00034   }
00035   g_assert (face->surfaces == NULL);
00036 
00037   (* GTS_OBJECT_CLASS (gts_face_class ())->parent_class->destroy) (object);
00038 }
00039 
00040 static void face_clone (GtsObject * clone, GtsObject * object)
00041 {
00042   (* GTS_OBJECT_CLASS (gts_face_class ())->parent_class->clone) (clone, 
00043                                                                  object);
00044   GTS_FACE (clone)->surfaces = NULL;
00045 }
00046 
00047 static void face_class_init (GtsFaceClass * klass)
00048 {
00049   GTS_OBJECT_CLASS (klass)->clone = face_clone;
00050   GTS_OBJECT_CLASS (klass)->destroy = face_destroy;
00051 }
00052 
00053 static void face_init (GtsFace * face)
00054 {
00055   face->surfaces = NULL;
00056 }
00057 
00063 GtsFaceClass * gts_face_class (void)
00064 {
00065   static GtsFaceClass * klass = NULL;
00066 
00067   if (klass == NULL) {
00068     GtsObjectClassInfo face_info = {
00069       "GtsFace",
00070       sizeof (GtsFace),
00071       sizeof (GtsFaceClass),
00072       (GtsObjectClassInitFunc) face_class_init,
00073       (GtsObjectInitFunc) face_init,
00074       (GtsArgSetFunc) NULL,
00075       (GtsArgGetFunc) NULL
00076     };
00077     klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_triangle_class ()), 
00078                                   &face_info);
00079   }
00080 
00081   return klass;
00082 }
00083 
00093 GtsFace * gts_face_new (GtsFaceClass * klass,
00094                         GtsEdge * e1, GtsEdge * e2, GtsEdge * e3)
00095 {
00096   GtsFace * f;
00097 
00098   f = GTS_FACE (gts_object_new (GTS_OBJECT_CLASS (klass)));
00099   gts_triangle_set (GTS_TRIANGLE (f), e1, e2, e3);
00100 
00101   return f;
00102 }
00103 
00111 gboolean gts_face_has_parent_surface (GtsFace * f, GtsSurface * s)
00112 {
00113   GSList * i;
00114 
00115   g_return_val_if_fail (f != NULL, FALSE);
00116 
00117   i = f->surfaces;
00118   while (i) {
00119     if (i->data == s)
00120       return TRUE;
00121     i = i->next;
00122   }
00123   return FALSE;
00124 }
00125 
00136 GSList * gts_faces_from_edges (GSList * edges, GtsSurface * s)
00137 {
00138   GHashTable * hash;
00139   GSList * faces = NULL, * i;
00140 
00141   hash = g_hash_table_new (NULL, NULL);
00142   i = edges;
00143   while (i) {
00144     GSList * j = GTS_EDGE (i->data)->triangles;
00145     while (j) {
00146       GtsTriangle * t = j->data;
00147       if (GTS_IS_FACE (t) &&
00148           (!s || gts_face_has_parent_surface (GTS_FACE (t), s)) && 
00149           g_hash_table_lookup (hash, t) == NULL) {
00150         faces = g_slist_prepend (faces, t);
00151         g_hash_table_insert (hash, t, i);
00152       }
00153       j = j->next;
00154     }
00155     i = i->next;
00156   }
00157   g_hash_table_destroy (hash);
00158 
00159   return faces;
00160 }
00161 
00169 guint gts_face_neighbor_number (GtsFace * f, GtsSurface * s)
00170 {
00171   GSList * i;
00172   guint nn = 0;
00173   GtsEdge * e[4], ** e1 = e;
00174   
00175   g_return_val_if_fail (f != NULL, 0);
00176   
00177   e[0] = GTS_TRIANGLE (f)->e1; 
00178   e[1] = GTS_TRIANGLE (f)->e2; 
00179   e[2] = GTS_TRIANGLE (f)->e3; 
00180   e[3] = NULL;
00181   while (*e1) {
00182     i = (*e1++)->triangles;
00183     while (i) {
00184       GtsTriangle * t = i->data;
00185       if (GTS_FACE (t) != f && 
00186           GTS_IS_FACE (t) && 
00187           (!s || gts_face_has_parent_surface (GTS_FACE (t), s)))
00188         nn++;
00189       i = i->next;
00190     }
00191   }
00192 
00193   return nn;
00194 }
00195 
00203 GSList * gts_face_neighbors (GtsFace * f, GtsSurface * s)
00204 {
00205   GSList * i, * list = NULL;
00206   GtsEdge * e[4], ** e1 = e;
00207   
00208   g_return_val_if_fail (f != NULL, NULL);
00209 
00210   e[0] = GTS_TRIANGLE (f)->e1; 
00211   e[1] = GTS_TRIANGLE (f)->e2; 
00212   e[2] = GTS_TRIANGLE (f)->e3; 
00213   e[3] = NULL;
00214   while (*e1) {
00215     i = (*e1++)->triangles;
00216     while (i) {
00217       GtsTriangle * t = i->data;
00218       if (GTS_FACE (t) != f && 
00219           GTS_IS_FACE (t) && 
00220           (!s || gts_face_has_parent_surface (GTS_FACE (t), s)))
00221         list = g_slist_prepend (list, t);
00222       i = i->next;
00223     }
00224   }
00225 
00226   return list;
00227 }
00228 
00238 void gts_face_foreach_neighbor (GtsFace * f, 
00239                                 GtsSurface * s, 
00240                                 GtsFunc func,
00241                                 gpointer data)
00242 {
00243   GSList * i;
00244   GtsEdge * e[4], ** e1 = e;
00245   
00246   g_return_if_fail (f != NULL);
00247   g_return_if_fail (func != NULL);
00248 
00249   e[0] = GTS_TRIANGLE (f)->e1;
00250   e[1] = GTS_TRIANGLE (f)->e2; 
00251   e[2] = GTS_TRIANGLE (f)->e3; 
00252   e[3] = NULL;
00253   while (*e1) {
00254     i = (*e1++)->triangles;
00255     while (i) {
00256       GtsTriangle * t = i->data;
00257       if (GTS_FACE (t) != f && 
00258           GTS_IS_FACE (t) && 
00259           (!s || gts_face_has_parent_surface (GTS_FACE (t), s)))
00260         (* func) (t, data);
00261       i = i->next;
00262     }
00263   }
00264 }
00265 
00266 static gboolean triangle_is_incompatible (GtsTriangle * t, GtsEdge * e, GtsSurface * s)
00267 {
00268   GSList * i = e->triangles;
00269 
00270   while (i) {
00271     if (i->data != t &&
00272         GTS_IS_FACE (i->data) &&
00273         gts_face_has_parent_surface (i->data, s) &&
00274         !gts_triangles_are_compatible (t, i->data, e))
00275       return TRUE;
00276     i = i->next;
00277   }
00278   return FALSE;
00279 }
00280 
00289 gboolean gts_face_is_compatible (GtsFace * f, GtsSurface * s)
00290 {
00291   g_return_val_if_fail (f != NULL, FALSE);
00292   g_return_val_if_fail (s != NULL, FALSE);
00293 
00294   return !(triangle_is_incompatible (GTS_TRIANGLE (f), GTS_TRIANGLE (f)->e1, s) ||
00295            triangle_is_incompatible (GTS_TRIANGLE (f), GTS_TRIANGLE (f)->e2, s) ||
00296            triangle_is_incompatible (GTS_TRIANGLE (f), GTS_TRIANGLE (f)->e3, s));
00297 }