Check sscanf() return value in GetValue().
[geda-pcb/whiteaudio.git] / gts / face.c
blobf6009f1a17c02fbc50a66a8bc539f53298726675
1 /* GTS - Library for the manipulation of triangulated surfaces
2 * Copyright (C) 1999 Stéphane Popinet
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gts.h"
22 gboolean gts_allow_floating_faces = FALSE;
24 static void face_destroy (GtsObject * object)
26 GtsFace * face = GTS_FACE (object);
27 GSList * i;
29 i = face->surfaces;
30 while (i) {
31 GSList * next = i->next;
32 gts_surface_remove_face (i->data, face);
33 i = next;
35 g_assert (face->surfaces == NULL);
37 (* GTS_OBJECT_CLASS (gts_face_class ())->parent_class->destroy) (object);
40 static void face_clone (GtsObject * clone, GtsObject * object)
42 (* GTS_OBJECT_CLASS (gts_face_class ())->parent_class->clone) (clone,
43 object);
44 GTS_FACE (clone)->surfaces = NULL;
47 static void face_class_init (GtsFaceClass * klass)
49 GTS_OBJECT_CLASS (klass)->clone = face_clone;
50 GTS_OBJECT_CLASS (klass)->destroy = face_destroy;
53 static void face_init (GtsFace * face)
55 face->surfaces = NULL;
58 /**
59 * gts_face_class:
61 * Returns: the #GtsFaceClass.
63 GtsFaceClass * gts_face_class (void)
65 static GtsFaceClass * klass = NULL;
67 if (klass == NULL) {
68 GtsObjectClassInfo face_info = {
69 "GtsFace",
70 sizeof (GtsFace),
71 sizeof (GtsFaceClass),
72 (GtsObjectClassInitFunc) face_class_init,
73 (GtsObjectInitFunc) face_init,
74 (GtsArgSetFunc) NULL,
75 (GtsArgGetFunc) NULL
77 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_triangle_class ()),
78 &face_info);
81 return klass;
84 /**
85 * gts_face_new:
86 * @klass: a #GtsFaceClass.
87 * @e1: a #GtsEdge.
88 * @e2: a #GtsEdge.
89 * @e3: a #GtsEdge.
91 * Returns: a new #GtsFace using @e1, @e2 and @e3 as edges.
93 GtsFace * gts_face_new (GtsFaceClass * klass,
94 GtsEdge * e1, GtsEdge * e2, GtsEdge * e3)
96 GtsFace * f;
98 f = GTS_FACE (gts_object_new (GTS_OBJECT_CLASS (klass)));
99 gts_triangle_set (GTS_TRIANGLE (f), e1, e2, e3);
101 return f;
105 * gts_face_has_parent_surface:
106 * @f: a #GtsFace.
107 * @s: a #GtsSurface.
109 * Returns: %TRUE if @f belongs to @s, %FALSE otherwise.
111 gboolean gts_face_has_parent_surface (GtsFace * f, GtsSurface * s)
113 GSList * i;
115 g_return_val_if_fail (f != NULL, FALSE);
117 i = f->surfaces;
118 while (i) {
119 if (i->data == s)
120 return TRUE;
121 i = i->next;
123 return FALSE;
127 * gts_faces_from_edges:
128 * @edges: a list of #GtsEdge.
129 * @s: a #GtsSurface or %NULL.
131 * Builds a list of unique faces which belong to @s and have
132 * one of their edges in @edges.
134 * Returns: the list of faces.
136 GSList * gts_faces_from_edges (GSList * edges, GtsSurface * s)
138 GHashTable * hash;
139 GSList * faces = NULL, * i;
141 hash = g_hash_table_new (NULL, NULL);
142 i = edges;
143 while (i) {
144 GSList * j = GTS_EDGE (i->data)->triangles;
145 while (j) {
146 GtsTriangle * t = j->data;
147 if (GTS_IS_FACE (t) &&
148 (!s || gts_face_has_parent_surface (GTS_FACE (t), s)) &&
149 g_hash_table_lookup (hash, t) == NULL) {
150 faces = g_slist_prepend (faces, t);
151 g_hash_table_insert (hash, t, i);
153 j = j->next;
155 i = i->next;
157 g_hash_table_destroy (hash);
159 return faces;
163 * gts_face_neighbor_number:
164 * @f: a #GtsFace.
165 * @s: a #GtsSurface or %NULL.
167 * Returns: the number of faces neighbors of @f and belonging to @s.
169 guint gts_face_neighbor_number (GtsFace * f, GtsSurface * s)
171 GSList * i;
172 guint nn = 0;
173 GtsEdge * e[4], ** e1 = e;
175 g_return_val_if_fail (f != NULL, 0);
177 e[0] = GTS_TRIANGLE (f)->e1;
178 e[1] = GTS_TRIANGLE (f)->e2;
179 e[2] = GTS_TRIANGLE (f)->e3;
180 e[3] = NULL;
181 while (*e1) {
182 i = (*e1++)->triangles;
183 while (i) {
184 GtsTriangle * t = i->data;
185 if (GTS_FACE (t) != f &&
186 GTS_IS_FACE (t) &&
187 (!s || gts_face_has_parent_surface (GTS_FACE (t), s)))
188 nn++;
189 i = i->next;
193 return nn;
197 * gts_face_neighbors:
198 * @f: a #GtsFace.
199 * @s: a #GtsSurface or %NULL.
201 * Returns: a list of unique #GtsFace neighbors of @f and belonging to @s.
203 GSList * gts_face_neighbors (GtsFace * f, GtsSurface * s)
205 GSList * i, * list = NULL;
206 GtsEdge * e[4], ** e1 = e;
208 g_return_val_if_fail (f != NULL, NULL);
210 e[0] = GTS_TRIANGLE (f)->e1;
211 e[1] = GTS_TRIANGLE (f)->e2;
212 e[2] = GTS_TRIANGLE (f)->e3;
213 e[3] = NULL;
214 while (*e1) {
215 i = (*e1++)->triangles;
216 while (i) {
217 GtsTriangle * t = i->data;
218 if (GTS_FACE (t) != f &&
219 GTS_IS_FACE (t) &&
220 (!s || gts_face_has_parent_surface (GTS_FACE (t), s)))
221 list = g_slist_prepend (list, t);
222 i = i->next;
226 return list;
230 * gts_face_foreach_neighbor:
231 * @f: a #GtsFace.
232 * @s: a #GtsSurface or %NULL.
233 * @func: a #GtsFunc.
234 * @data: user data to pass to @func.
236 * Calls @func for each neighbor of @f belonging to @s (if not %NULL).
238 void gts_face_foreach_neighbor (GtsFace * f,
239 GtsSurface * s,
240 GtsFunc func,
241 gpointer data)
243 GSList * i;
244 GtsEdge * e[4], ** e1 = e;
246 g_return_if_fail (f != NULL);
247 g_return_if_fail (func != NULL);
249 e[0] = GTS_TRIANGLE (f)->e1;
250 e[1] = GTS_TRIANGLE (f)->e2;
251 e[2] = GTS_TRIANGLE (f)->e3;
252 e[3] = NULL;
253 while (*e1) {
254 i = (*e1++)->triangles;
255 while (i) {
256 GtsTriangle * t = i->data;
257 if (GTS_FACE (t) != f &&
258 GTS_IS_FACE (t) &&
259 (!s || gts_face_has_parent_surface (GTS_FACE (t), s)))
260 (* func) (t, data);
261 i = i->next;
266 static gboolean triangle_is_incompatible (GtsTriangle * t, GtsEdge * e, GtsSurface * s)
268 GSList * i = e->triangles;
270 while (i) {
271 if (i->data != t &&
272 GTS_IS_FACE (i->data) &&
273 gts_face_has_parent_surface (i->data, s) &&
274 !gts_triangles_are_compatible (t, i->data, e))
275 return TRUE;
276 i = i->next;
278 return FALSE;
282 * gts_face_is_compatible:
283 * @f: a #GtsFace.
284 * @s: a #GtsSurface.
286 * Returns: %TRUE if @f is compatible with all its neighbors belonging
287 * to @s, %FALSE otherwise.
289 gboolean gts_face_is_compatible (GtsFace * f, GtsSurface * s)
291 g_return_val_if_fail (f != NULL, FALSE);
292 g_return_val_if_fail (s != NULL, FALSE);
294 return !(triangle_is_incompatible (GTS_TRIANGLE (f), GTS_TRIANGLE (f)->e1, s) ||
295 triangle_is_incompatible (GTS_TRIANGLE (f), GTS_TRIANGLE (f)->e2, s) ||
296 triangle_is_incompatible (GTS_TRIANGLE (f), GTS_TRIANGLE (f)->e3, s));