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_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 }