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 <stdlib.h> 00021 #include <string.h> 00022 #include "gts.h" 00023 00024 #define HEAP_INSERT_HSPLIT(h, e) ((e)->index = gts_eheap_insert (h, e)) 00025 #define HEAP_REMOVE_HSPLIT(h, e) (gts_eheap_remove (h, (e)->index),\ 00026 (e)->index = NULL) 00027 00028 static void hsplit_init (GtsHSplit * hsplit) 00029 { 00030 hsplit->index = NULL; 00031 hsplit->parent = NULL; 00032 hsplit->nchild = 0; 00033 } 00034 00040 GtsHSplitClass * gts_hsplit_class (void) 00041 { 00042 static GtsHSplitClass * klass = NULL; 00043 00044 if (klass == NULL) { 00045 GtsObjectClassInfo hsplit_info = { 00046 "GtsHSplit", 00047 sizeof (GtsHSplit), 00048 sizeof (GtsHSplitClass), 00049 (GtsObjectClassInitFunc) NULL, 00050 (GtsObjectInitFunc) hsplit_init, 00051 (GtsArgSetFunc) NULL, 00052 (GtsArgGetFunc) NULL 00053 }; 00054 klass = gts_object_class_new (GTS_OBJECT_CLASS (gts_split_class ()), 00055 &hsplit_info); 00056 } 00057 00058 return klass; 00059 } 00060 00068 GtsHSplit * gts_hsplit_new (GtsHSplitClass * klass, GtsSplit * vs) 00069 { 00070 GtsHSplit * hs; 00071 00072 g_return_val_if_fail (vs != NULL, NULL); 00073 00074 hs = GTS_HSPLIT (gts_object_new (GTS_OBJECT_CLASS (klass))); 00075 memcpy (hs, vs, sizeof (GtsSplit)); 00076 GTS_OBJECT (hs)->reserved = NULL; 00077 00078 return hs; 00079 } 00080 00089 void gts_hsplit_collapse (GtsHSplit * hs, 00090 GtsHSurface * hsurface) 00091 { 00092 GtsHSplit * parent; 00093 GtsSplit * vs; 00094 00095 g_return_if_fail (hs != NULL); 00096 g_return_if_fail (hs->nchild == 2); 00097 g_return_if_fail (hsurface != NULL); 00098 00099 gts_split_collapse (GTS_SPLIT (hs), hsurface->s->edge_class, NULL); 00100 00101 hsurface->nvertex--; 00102 hs->nchild = 0; 00103 HEAP_REMOVE_HSPLIT (hsurface->collapsable, hs); 00104 HEAP_INSERT_HSPLIT (hsurface->expandable, hs); 00105 00106 vs = GTS_SPLIT (hs); 00107 if (GTS_IS_HSPLIT (vs->v1)) 00108 HEAP_REMOVE_HSPLIT (hsurface->expandable, GTS_HSPLIT (vs->v1)); 00109 if (GTS_IS_HSPLIT (vs->v2)) 00110 HEAP_REMOVE_HSPLIT (hsurface->expandable, GTS_HSPLIT (vs->v2)); 00111 00112 parent = hs->parent; 00113 if (parent && ++parent->nchild == 2) 00114 HEAP_INSERT_HSPLIT (hsurface->collapsable, parent); 00115 } 00116 00125 void gts_hsplit_expand (GtsHSplit * hs, 00126 GtsHSurface * hsurface) 00127 { 00128 GtsHSplit * parent; 00129 GtsSplit * vs; 00130 00131 g_return_if_fail (hs != NULL); 00132 g_return_if_fail (hsurface != NULL); 00133 g_return_if_fail (hs->nchild == 0); 00134 00135 gts_split_expand (GTS_SPLIT (hs), hsurface->s, hsurface->s->edge_class); 00136 hsurface->nvertex++; 00137 hs->nchild = 2; 00138 HEAP_REMOVE_HSPLIT (hsurface->expandable, hs); 00139 HEAP_INSERT_HSPLIT (hsurface->collapsable, hs); 00140 00141 vs = GTS_SPLIT (hs); 00142 if (GTS_IS_HSPLIT (vs->v1)) 00143 HEAP_INSERT_HSPLIT (hsurface->expandable, GTS_HSPLIT (vs->v1)); 00144 if (GTS_IS_HSPLIT (vs->v2)) 00145 HEAP_INSERT_HSPLIT (hsurface->expandable, GTS_HSPLIT (vs->v2)); 00146 00147 parent = hs->parent; 00148 if (parent && parent->nchild-- == 2) 00149 HEAP_REMOVE_HSPLIT (hsurface->collapsable, parent); 00150 } 00151 00152 static void hsurface_destroy (GtsObject * object) 00153 { 00154 GtsHSurface * hs = GTS_HSURFACE (object); 00155 00156 gts_hsurface_traverse (hs, G_POST_ORDER, -1, 00157 (GtsSplitTraverseFunc) gts_object_destroy, 00158 NULL); 00159 g_slist_free (hs->roots); 00160 if (hs->expandable) 00161 gts_eheap_destroy (hs->expandable); 00162 if (hs->collapsable) 00163 gts_eheap_destroy (hs->collapsable); 00164 g_ptr_array_free (hs->split, TRUE); 00165 00166 (* GTS_OBJECT_CLASS (gts_hsurface_class ())->parent_class->destroy) (object); 00167 } 00168 00169 static void hsurface_class_init (GtsObjectClass * klass) 00170 { 00171 klass->destroy = hsurface_destroy; 00172 } 00173 00174 static void hsurface_init (GtsHSurface * hsurface) 00175 { 00176 hsurface->s = NULL; 00177 hsurface->roots = NULL; 00178 hsurface->expandable = hsurface->collapsable = NULL; 00179 hsurface->split = g_ptr_array_new (); 00180 hsurface->nvertex = 0; 00181 } 00182 00188 GtsHSurfaceClass * gts_hsurface_class (void) 00189 { 00190 static GtsHSurfaceClass * klass = NULL; 00191 00192 if (klass == NULL) { 00193 GtsObjectClassInfo hsurface_info = { 00194 "GtsHSurface", 00195 sizeof (GtsHSurface), 00196 sizeof (GtsHSurfaceClass), 00197 (GtsObjectClassInitFunc) hsurface_class_init, 00198 (GtsObjectInitFunc) hsurface_init, 00199 (GtsArgSetFunc) NULL, 00200 (GtsArgGetFunc) NULL 00201 }; 00202 klass = gts_object_class_new (gts_object_class (), 00203 &hsurface_info); 00204 } 00205 00206 return klass; 00207 } 00208 00225 GtsHSurface * gts_hsurface_new (GtsHSurfaceClass * klass, 00226 GtsHSplitClass * hsplit_class, 00227 GtsPSurface * psurface, 00228 GtsKeyFunc expand_key, 00229 gpointer expand_data, 00230 GtsKeyFunc collapse_key, 00231 gpointer collapse_data) 00232 { 00233 GtsHSurface * hsurface; 00234 00235 g_return_val_if_fail (klass != NULL, NULL); 00236 g_return_val_if_fail (hsplit_class != NULL, NULL); 00237 g_return_val_if_fail (psurface != NULL, NULL); 00238 g_return_val_if_fail (expand_key != NULL, NULL); 00239 g_return_val_if_fail (collapse_key != NULL, NULL); 00240 00241 hsurface = GTS_HSURFACE (gts_object_new (GTS_OBJECT_CLASS (klass))); 00242 hsurface->s = psurface->s; 00243 hsurface->expandable = gts_eheap_new (expand_key, expand_data); 00244 hsurface->collapsable = gts_eheap_new (collapse_key, collapse_data); 00245 g_ptr_array_set_size (hsurface->split, psurface->split->len); 00246 00247 while (gts_psurface_remove_vertex (psurface)) 00248 ; 00249 while (psurface->pos) { 00250 GtsSplit * vs = g_ptr_array_index (psurface->split, psurface->pos - 1); 00251 GtsHSplit * hs = gts_hsplit_new (hsplit_class, vs); 00252 00253 g_ptr_array_index (hsurface->split, psurface->pos - 1) = hs; 00254 psurface->pos--; 00255 00256 hs->parent = GTS_OBJECT (vs)->reserved; 00257 if (hs->parent) { 00258 GtsSplit * vsp = GTS_SPLIT (hs->parent); 00259 00260 if (vsp->v1 == GTS_OBJECT (vs)) { 00261 g_assert (vsp->v2 != GTS_OBJECT (vs)); 00262 vsp->v1 = GTS_OBJECT (hs); 00263 } 00264 else { 00265 g_assert (vsp->v2 == GTS_OBJECT (vs)); 00266 vsp->v2 = GTS_OBJECT (hs); 00267 } 00268 } 00269 else 00270 hsurface->roots = g_slist_prepend (hsurface->roots, hs); 00271 00272 hs->nchild = 0; 00273 if (GTS_IS_SPLIT (vs->v1)) 00274 GTS_OBJECT (vs->v1)->reserved = hs; 00275 else 00276 hs->nchild++; 00277 if (GTS_IS_SPLIT (vs->v2)) 00278 GTS_OBJECT (vs->v2)->reserved = hs; 00279 else 00280 hs->nchild++; 00281 00282 gts_split_expand (vs, psurface->s, psurface->s->edge_class); 00283 00284 if (hs->nchild == 2) 00285 HEAP_INSERT_HSPLIT (hsurface->collapsable, hs); 00286 } 00287 00288 hsurface->nvertex = gts_surface_vertex_number (hsurface->s); 00289 gts_object_destroy (GTS_OBJECT (psurface)); 00290 00291 return hsurface; 00292 } 00293 00309 void gts_hsurface_traverse (GtsHSurface * hsurface, 00310 GTraverseType order, 00311 gint depth, 00312 GtsSplitTraverseFunc func, 00313 gpointer data) 00314 { 00315 GSList * i; 00316 00317 g_return_if_fail (hsurface != NULL); 00318 g_return_if_fail (func != NULL); 00319 g_return_if_fail (order < G_LEVEL_ORDER); 00320 g_return_if_fail (depth == -1 || depth > 0); 00321 00322 i = hsurface->roots; 00323 while (i) { 00324 gts_split_traverse (i->data, order, depth, func, data); 00325 i = i->next; 00326 } 00327 } 00328 00343 void gts_hsurface_foreach (GtsHSurface * hsurface, 00344 GTraverseType order, 00345 GtsFunc func, 00346 gpointer data) 00347 { 00348 GtsHSplit * hs; 00349 guint i = 0, len; 00350 gboolean stop = FALSE; 00351 00352 g_return_if_fail (hsurface != NULL); 00353 g_return_if_fail (func != NULL); 00354 g_return_if_fail (order == G_PRE_ORDER || order == G_POST_ORDER); 00355 00356 while ((hs = gts_eheap_top (hsurface->expandable, NULL))) 00357 gts_hsplit_expand (hs, hsurface); 00358 00359 len = hsurface->split->len; 00360 switch (order) { 00361 case G_PRE_ORDER: 00362 while (i < len && !stop) { 00363 GtsHSplit * hs = g_ptr_array_index (hsurface->split, i); 00364 stop = (*func) (hs, data); 00365 if (!stop) 00366 gts_hsplit_collapse (hs, hsurface); 00367 i++; 00368 } 00369 break; 00370 case G_POST_ORDER: 00371 while (i < len && !stop) { 00372 GtsHSplit * hs = g_ptr_array_index (hsurface->split, i); 00373 gts_hsplit_collapse (hs, hsurface); 00374 stop = (*func) (hs, data); 00375 i++; 00376 } 00377 break; 00378 default: 00379 g_assert_not_reached (); 00380 } 00381 } 00382 00389 guint gts_hsurface_height (GtsHSurface * hsurface) 00390 { 00391 GSList * i; 00392 guint height = 0; 00393 00394 g_return_val_if_fail (hsurface != NULL, 0); 00395 00396 i = hsurface->roots; 00397 while (i) { 00398 guint tmp_height = gts_split_height (i->data); 00399 if (tmp_height > height) 00400 height = tmp_height; 00401 i = i->next; 00402 } 00403 00404 return height; 00405 }