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 #ifdef DEBUG 00024 #ifdef DEBUG_FUNCTIONS 00025 #include "gts-private.h" 00026 #else 00027 #define DEBUG_FUNCTIONS 00028 #include "gts-private.h" 00029 #undef DEBUG_FUNCTIONS 00030 #endif 00031 #endif 00032 00033 #define DYNAMIC_SPLIT 00034 #define NEW 00035 00036 /* #define DEBUG 00037 #define DEBUG_HEXPAND 00038 #define DEBUG_EXPAND */ 00039 00040 struct _GtsSplitCFace { 00041 GtsFace * f; 00042 GtsTriangle ** a1, ** a2; 00043 }; 00044 00045 typedef struct _CFace CFace; 00046 typedef struct _CFaceClass CFaceClass; 00047 00048 struct _CFace { 00049 GtsObject object; 00050 00051 GtsSplit * parent_split; 00052 GtsTriangle * t; 00053 guint flags; 00054 }; 00055 /* the size of the CFace structure must be smaller or equal to the size 00056 of the GtsFace structure as both structures use the same memory location */ 00057 00058 struct _CFaceClass { 00059 GtsObjectClass parent_class; 00060 }; 00061 00062 #define IS_CFACE(obj) (gts_object_is_from_class (obj, cface_class ())) 00063 #define CFACE(obj) ((CFace *) obj) 00064 #define CFACE_ORIENTATION(cf) ((cf)->flags & 0x1) 00065 #define CFACE_ORIENTATION_DIRECT(cf) ((cf)->flags |= 0x1) 00066 #define CFACE_VVS(cf) ((cf)->flags & 0x2) 00067 #define CFACE_VVS_DIRECT(cf) ((cf)->flags |= 0x2) 00068 #define CFACE_E1 0x4 00069 #define CFACE_E2 0x8 00070 #define CFACE_KEEP_VVS 0x10 00071 00072 #define ROTATE_ORIENT(e, e1, e2, e3) { if (e1 == e) { e1 = e2; e2 = e3; }\ 00073 else if (e2 == e) { e2 = e1; e1 = e3; }\ 00074 else g_assert (e3 == e); } 00075 #define SEGMENT_USE_VERTEX(s, v) ((s)->v1 == v || (s)->v2 == v) 00076 #define TRIANGLE_REPLACE_EDGE(t, e, with) { if ((t)->e1 == e)\ 00077 (t)->e1 = with;\ 00078 else if ((t)->e2 == e)\ 00079 (t)->e2 = with;\ 00080 else {\ 00081 g_assert ((t)->e3 == e);\ 00082 (t)->e3 = with;\ 00083 }\ 00084 } 00085 00086 #define HEAP_INSERT_OBJECT(h, e) (GTS_OBJECT (e)->reserved =\ 00087 gts_eheap_insert (h, e)) 00088 #define HEAP_REMOVE_OBJECT(h, e) (gts_eheap_remove (h, GTS_OBJECT (e)->reserved),\ 00089 GTS_OBJECT (e)->reserved = NULL) 00090 00091 static GtsObjectClass * cface_class (void) 00092 { 00093 static GtsObjectClass * klass = NULL; 00094 00095 if (klass == NULL) { 00096 GtsObjectClassInfo cface_info = { 00097 "GtsCFace", 00098 sizeof (CFace), 00099 sizeof (CFaceClass), 00100 (GtsObjectClassInitFunc) NULL, 00101 (GtsObjectInitFunc) NULL, 00102 (GtsArgSetFunc) NULL, 00103 (GtsArgGetFunc) NULL 00104 }; 00105 klass = gts_object_class_new (gts_object_class (), &cface_info); 00106 g_assert (sizeof (CFace) <= sizeof (GtsFace)); 00107 } 00108 00109 return klass; 00110 } 00111 00112 /* Replace @e with @with for all the triangles using @e but @f. 00113 Destroys @e and removes it from @heap (if not %NULL). 00114 Returns a triangle using e different from f or %NULL. */ 00115 static GtsTriangle * replace_edge_collapse (GtsEdge * e, 00116 GtsEdge * with, 00117 CFace * cf, 00118 GtsEHeap * heap 00119 #ifdef DYNAMIC_SPLIT 00120 , GtsTriangle *** a1 00121 #endif 00122 #ifdef NEW 00123 , guint edge_flag 00124 #endif 00125 ) 00126 { 00127 GSList * i; 00128 GtsTriangle * rt = NULL; 00129 #ifdef DYNAMIC_SPLIT 00130 guint size; 00131 GtsTriangle ** a; 00132 #endif 00133 00134 #ifdef NEW 00135 i = e->triangles; 00136 e->triangles = NULL; 00137 size = g_slist_length (i)*sizeof (GtsTriangle *); 00138 *a1 = a = g_malloc (size > 0 ? size : sizeof (GtsTriangle *)); 00139 while (i) { 00140 GtsTriangle * t = i->data; 00141 GSList * next = i->next; 00142 if (t != ((GtsTriangle *) cf)) { 00143 if (IS_CFACE (t)) { 00144 i->next = e->triangles; 00145 e->triangles = i; 00146 /* set the edge given by edge_flag (CFACE_E1 or CFACE_E2) */ 00147 GTS_OBJECT (t)->reserved = GUINT_TO_POINTER (edge_flag); 00148 cf->flags |= CFACE_KEEP_VVS; 00149 } 00150 else { 00151 TRIANGLE_REPLACE_EDGE (t, e, with); 00152 i->next = with->triangles; 00153 with->triangles = i; 00154 rt = t; 00155 *(a++) = t; 00156 } 00157 } 00158 else 00159 g_slist_free_1 (i); 00160 i = next; 00161 } 00162 *a = NULL; 00163 if (!e->triangles) { 00164 if (heap) 00165 HEAP_REMOVE_OBJECT (heap, e); 00166 gts_object_destroy (GTS_OBJECT (e)); 00167 } 00168 #else /* not NEW */ 00169 i = e->triangles; 00170 #ifdef DYNAMIC_SPLIT 00171 size = g_slist_length (i)*sizeof (GtsTriangle *); 00172 *a1 = a = g_malloc (size > 0 ? size : sizeof (GtsTriangle *)); 00173 #endif 00174 while (i) { 00175 GtsTriangle * t = i->data; 00176 GSList * next = i->next; 00177 if (t != ((GtsTriangle *) cf)) { 00178 TRIANGLE_REPLACE_EDGE (t, e, with); 00179 i->next = with->triangles; 00180 with->triangles = i; 00181 rt = t; 00182 #ifdef DYNAMIC_SPLIT 00183 *(a++) = t; 00184 #endif 00185 } 00186 else 00187 g_slist_free_1 (i); 00188 i = next; 00189 } 00190 #ifdef DYNAMIC_SPLIT 00191 *a = NULL; 00192 #endif 00193 if (heap) 00194 HEAP_REMOVE_OBJECT (heap, e); 00195 e->triangles = NULL; 00196 gts_object_destroy (GTS_OBJECT (e)); 00197 #endif /* NEW */ 00198 00199 return rt; 00200 } 00201 00202 static CFace * cface_new (GtsFace * f, 00203 GtsEdge * e, 00204 GtsVertex * v1, 00205 GtsVertex * v2, 00206 GtsSplit * vs, 00207 GtsEHeap * heap, 00208 GtsEdgeClass * klass 00209 #ifdef DYNAMIC_SPLIT 00210 , GtsSplitCFace * scf 00211 #endif 00212 ) 00213 { 00214 CFace * cf; 00215 GtsVertex * v; 00216 GtsEdge * e1, * e2, * e3, * vvs; 00217 GSList * i; 00218 GtsTriangle * t, * t1 = NULL, * t2 = NULL; 00219 guint flags; 00220 00221 g_return_val_if_fail (f != NULL, NULL); 00222 #ifndef NEW 00223 g_return_val_if_fail (GTS_IS_FACE (f), NULL); 00224 #endif 00225 g_return_val_if_fail (e != NULL, NULL); 00226 g_return_val_if_fail (vs != NULL, NULL); 00227 00228 t = ((GtsTriangle *) f); 00229 if (heap) 00230 g_return_val_if_fail (!gts_triangle_is_duplicate (t), NULL); 00231 00232 #ifdef NEW 00233 /* get CFACE_E1 and CFACE_E2 info */ 00234 flags = GPOINTER_TO_UINT (GTS_OBJECT (f)->reserved); 00235 #endif 00236 GTS_OBJECT_SET_FLAGS (f, GTS_DESTROYED); 00237 00238 i = f->surfaces; 00239 while (i) { 00240 GSList * next = i->next; 00241 gts_surface_remove_face (i->data, f); 00242 i = next; 00243 } 00244 g_slist_free (f->surfaces); 00245 00246 e1 = t->e1; e2 = t->e2; e3 = t->e3; 00247 ROTATE_ORIENT (e, e1, e2, e3); 00248 00249 cf = (CFace *) f; 00250 #ifndef NEW 00251 GTS_OBJECT (cf)->klass = cface_class (); 00252 #else 00253 cf->flags = flags; 00254 #endif 00255 gts_object_init (GTS_OBJECT (cf), cface_class ()); 00256 cf->parent_split = vs; 00257 00258 if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e1), v2)) { 00259 CFACE_ORIENTATION_DIRECT (cf); /* v1->v2->v */ 00260 e3 = e1; e1 = e2; e2 = e3; 00261 } 00262 v = GTS_SEGMENT (e1)->v1 == v1 ? 00263 GTS_SEGMENT (e1)->v2 : GTS_SEGMENT (e1)->v1; 00264 #ifdef NEW 00265 if ((cf->flags & CFACE_E1) || (cf->flags & CFACE_E2)) { 00266 vvs = GTS_EDGE (gts_vertices_are_connected (vs->v, v)); 00267 g_assert (vvs != NULL); 00268 } else 00269 #endif 00270 vvs = gts_edge_new (klass, v, vs->v); 00271 00272 t1 = replace_edge_collapse (e1, vvs, cf, heap 00273 #ifdef DYNAMIC_SPLIT 00274 , &scf->a1 00275 #endif 00276 #ifdef NEW 00277 , CFACE_E1 00278 #endif 00279 ); 00280 t2 = replace_edge_collapse (e2, vvs, cf, heap 00281 #ifdef DYNAMIC_SPLIT 00282 , &scf->a2 00283 #endif 00284 #ifdef NEW 00285 , CFACE_E2 00286 #endif 00287 ); 00288 t = cf->t = t1 ? t1 : t2; 00289 g_assert (t); 00290 00291 /* set up flags necessary to find vvs */ 00292 if (t->e1 == vvs) e2 = t->e2; 00293 else if (t->e2 == vvs) e2 = t->e3; 00294 else { 00295 g_assert (t->e3 == vvs); 00296 e2 = t->e1; 00297 } 00298 if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e2), v)) 00299 CFACE_VVS_DIRECT (cf); 00300 00301 return cf; 00302 } 00303 00304 static void find_vvs (GtsVertex * vs, 00305 GtsTriangle * t, 00306 GtsVertex ** v, GtsEdge ** vvs, 00307 gboolean orientation) 00308 { 00309 GtsEdge * e1 = t->e1, * e2 = t->e2, * e3 = t->e3, * tmp; 00310 00311 if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e2), vs)) { 00312 tmp = e1; e1 = e2; e2 = e3; e3 = tmp; 00313 } 00314 else if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e3), vs)) { 00315 tmp = e1; e1 = e3; e3 = e2; e2 = tmp; 00316 } 00317 else 00318 g_assert (SEGMENT_USE_VERTEX (GTS_SEGMENT (e1), vs)); 00319 if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e2), vs) || 00320 !gts_segments_touch (GTS_SEGMENT (e1), GTS_SEGMENT (e2))) { 00321 tmp = e1; e1 = e2; e2 = e3; e3 = tmp; 00322 g_assert (gts_segments_touch (GTS_SEGMENT (e1), GTS_SEGMENT (e2))); 00323 } 00324 00325 *vvs = orientation ? e1 : e3; 00326 00327 if (GTS_SEGMENT (*vvs)->v1 != vs) { 00328 g_assert (GTS_SEGMENT (*vvs)->v2 == vs); 00329 *v = GTS_SEGMENT (*vvs)->v1; 00330 } 00331 else 00332 *v = GTS_SEGMENT (*vvs)->v2; 00333 } 00334 00335 static void replace_edge_expand (GtsEdge * e, 00336 GtsEdge * with, 00337 GtsTriangle ** a, 00338 GtsVertex * v) 00339 { 00340 GtsTriangle ** i = a, * t; 00341 00342 while ((t = *(i++))) { 00343 #ifdef DEBUG_EXPAND 00344 g_assert (!IS_CFACE (t)); 00345 fprintf (stderr, "replacing %p->%d: e: %p->%d with: %p->%d\n", 00346 t, id (t), e, id (e), with, id (with)); 00347 #endif 00348 TRIANGLE_REPLACE_EDGE (t, e, with); 00349 with->triangles = g_slist_prepend (with->triangles, t); 00350 if (GTS_OBJECT (t)->reserved) { 00351 /* apart from the triangles having e as an edge, t is the only 00352 triangle using v */ 00353 g_assert (GTS_OBJECT (t)->reserved == v); 00354 GTS_OBJECT (t)->reserved = NULL; 00355 } 00356 else 00357 GTS_OBJECT (t)->reserved = v; 00358 } 00359 } 00360 00361 static void cface_expand (CFace * cf, 00362 GtsTriangle ** a1, 00363 GtsTriangle ** a2, 00364 GtsEdge * e, 00365 GtsVertex * v1, 00366 GtsVertex * v2, 00367 GtsVertex * vs, 00368 GtsEdgeClass * klass) 00369 { 00370 GtsVertex * v; 00371 GtsEdge * e1, * e2, * vvs; 00372 gboolean orientation; 00373 guint flags; 00374 00375 g_return_if_fail (cf != NULL); 00376 g_return_if_fail (IS_CFACE (cf)); 00377 g_return_if_fail (e != NULL); 00378 g_return_if_fail (vs != NULL); 00379 00380 flags = cf->flags; 00381 orientation = CFACE_ORIENTATION (cf); 00382 00383 find_vvs (vs, cf->t, &v, &vvs, CFACE_VVS (cf)); 00384 00385 #ifdef NEW 00386 if (flags & CFACE_E1) 00387 e1 = GTS_EDGE (gts_vertices_are_connected (v1, v)); 00388 else 00389 e1 = gts_edge_new (klass, v, v1); 00390 if (flags & CFACE_E2) 00391 e2 = GTS_EDGE (gts_vertices_are_connected (v2, v)); 00392 else 00393 e2 = gts_edge_new (klass, v, v2); 00394 #else 00395 e1 = gts_edge_new (v, v1); 00396 e2 = gts_edge_new (v, v2); 00397 #endif 00398 00399 replace_edge_expand (vvs, e1, a1, v1); 00400 replace_edge_expand (vvs, e2, a2, v2); 00401 00402 #ifdef NEW 00403 if (!(flags & CFACE_KEEP_VVS)) { 00404 g_slist_free (vvs->triangles); 00405 vvs->triangles = NULL; 00406 gts_object_destroy (GTS_OBJECT (vvs)); 00407 } 00408 #else 00409 g_slist_free (vvs->triangles); 00410 vvs->triangles = NULL; 00411 gts_object_destroy (GTS_OBJECT (vvs)); 00412 #endif 00413 00414 /* gts_face_new : because I am "creating" a face */ 00415 GTS_OBJECT (cf)->klass = GTS_OBJECT_CLASS (gts_face_class ()); 00416 gts_object_init (GTS_OBJECT (cf), GTS_OBJECT (cf)->klass); 00417 00418 if (orientation) 00419 gts_triangle_set (GTS_TRIANGLE (cf), e, e2, e1); 00420 else 00421 gts_triangle_set (GTS_TRIANGLE (cf), e, e1, e2); 00422 } 00423 00424 static void split_destroy (GtsObject * object) 00425 { 00426 GtsSplit * vs = GTS_SPLIT (object); 00427 guint i = vs->ncf; 00428 GtsSplitCFace * cf = vs->cfaces; 00429 00430 while (i--) { 00431 if (IS_CFACE (cf->f)) 00432 gts_object_destroy (GTS_OBJECT (cf->f)); 00433 g_free (cf->a1); 00434 g_free (cf->a2); 00435 cf++; 00436 } 00437 g_free (vs->cfaces); 00438 00439 if (!gts_allow_floating_vertices && vs->v && vs->v->segments == NULL) 00440 gts_object_destroy (GTS_OBJECT (vs->v)); 00441 00442 (* GTS_OBJECT_CLASS (gts_split_class ())->parent_class->destroy) (object); 00443 } 00444 00445 static void split_class_init (GtsObjectClass * klass) 00446 { 00447 klass->destroy = split_destroy; 00448 } 00449 00450 static void split_init (GtsSplit * split) 00451 { 00452 split->v1 = split->v2 = NULL; 00453 split->v = NULL; 00454 split->cfaces = NULL; 00455 split->ncf = 0; 00456 } 00457 00463 GtsSplitClass * gts_split_class (void) 00464 { 00465 static GtsSplitClass * klass = NULL; 00466 00467 if (klass == NULL) { 00468 GtsObjectClassInfo split_info = { 00469 "GtsSplit", 00470 sizeof (GtsSplit), 00471 sizeof (GtsSplitClass), 00472 (GtsObjectClassInitFunc) split_class_init, 00473 (GtsObjectInitFunc) split_init, 00474 (GtsArgSetFunc) NULL, 00475 (GtsArgGetFunc) NULL 00476 }; 00477 klass = gts_object_class_new (gts_object_class (), 00478 &split_info); 00479 } 00480 00481 return klass; 00482 } 00483 00484 #ifdef DEBUG 00485 static gboolean edge_collapse_is_valid (GtsEdge * e) 00486 { 00487 GSList * i; 00488 00489 g_return_val_if_fail (e != NULL, FALSE); 00490 00491 if (gts_segment_is_duplicate (GTS_SEGMENT (e))) { 00492 g_warning ("collapsing duplicate edge"); 00493 return FALSE; 00494 } 00495 00496 i = GTS_SEGMENT (e)->v1->segments; 00497 while (i) { 00498 GtsEdge * e1 = i->data; 00499 if (e1 != e && GTS_IS_EDGE (e1)) { 00500 GtsEdge * e2 = NULL; 00501 GSList * j = GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e)->v1 ? 00502 GTS_SEGMENT (e1)->v2->segments : GTS_SEGMENT (e1)->v1->segments; 00503 while (j && !e2) { 00504 GtsEdge * e1 = j->data; 00505 if (GTS_IS_EDGE (e1) && 00506 (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e)->v2 || 00507 GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e)->v2)) 00508 e2 = e1; 00509 j = j->next; 00510 } 00511 if (e2 && !gts_triangle_use_edges (e, e1, e2)) { 00512 g_warning ("collapsing empty triangle"); 00513 return FALSE; 00514 } 00515 } 00516 i = i->next; 00517 } 00518 00519 if (gts_edge_is_boundary (e, NULL)) { 00520 GtsTriangle * t = e->triangles->data; 00521 if (gts_edge_is_boundary (t->e1, NULL) && 00522 gts_edge_is_boundary (t->e2, NULL) && 00523 gts_edge_is_boundary (t->e3, NULL)) { 00524 g_warning ("collapsing single triangle"); 00525 return FALSE; 00526 } 00527 } 00528 else { 00529 if (gts_vertex_is_boundary (GTS_SEGMENT (e)->v1, NULL) && 00530 gts_vertex_is_boundary (GTS_SEGMENT (e)->v2, NULL)) { 00531 g_warning ("collapsing two sides of a strip"); 00532 return FALSE; 00533 } 00534 if (gts_edge_belongs_to_tetrahedron (e)) { 00535 g_warning ("collapsing tetrahedron"); 00536 return FALSE; 00537 } 00538 } 00539 00540 return TRUE; 00541 } 00542 #endif /* DEBUG */ 00543 00554 void gts_split_collapse (GtsSplit * vs, 00555 GtsEdgeClass * klass, 00556 GtsEHeap * heap) 00557 { 00558 GtsEdge * e; 00559 GtsVertex * v, * v1, * v2; 00560 GSList * i, * end; 00561 #ifdef DYNAMIC_SPLIT 00562 GtsSplitCFace * cf; 00563 guint j; 00564 #endif 00565 #ifdef DEBUG 00566 gboolean invalid = FALSE; 00567 static guint ninvalid = 0; 00568 #endif 00569 00570 g_return_if_fail (vs != NULL); 00571 g_return_if_fail (klass != NULL); 00572 00573 v = vs->v; 00574 00575 g_return_if_fail (v->segments == NULL); 00576 00577 /* we don't want to destroy vertices */ 00578 gts_allow_floating_vertices = TRUE; 00579 00580 v1 = GTS_SPLIT_V1 (vs); 00581 v2 = GTS_SPLIT_V2 (vs); 00582 e = GTS_EDGE (gts_vertices_are_connected (v1, v2)); 00583 g_assert (e != NULL); 00584 00585 #ifdef DEBUG 00586 fprintf (stderr, "collapsing %p: v1: %p v2: %p v: %p\n", vs, v1, v2, v); 00587 if (!edge_collapse_is_valid (e)) { 00588 char fname[80]; 00589 FILE * fptr; 00590 GSList * triangles, * i; 00591 00592 g_warning ("invalid edge collapse"); 00593 invalid = TRUE; 00594 sprintf (fname, "invalid.%d", ninvalid); 00595 fptr = fopen (fname, "wt"); 00596 gts_write_segment (GTS_SEGMENT (e), GTS_POINT (v), fptr); 00597 triangles = gts_vertex_triangles (v1, NULL); 00598 triangles = gts_vertex_triangles (v2, triangles); 00599 i = triangles; 00600 while (i) { 00601 gts_write_triangle (i->data, GTS_POINT (v), fptr); 00602 i = i->next; 00603 } 00604 g_slist_free (triangles); 00605 fclose (fptr); 00606 } 00607 #endif 00608 00609 i = e->triangles; 00610 #ifdef DYNAMIC_SPLIT 00611 cf = vs->cfaces; 00612 j = vs->ncf; 00613 while (j--) { 00614 g_free (cf->a1); 00615 g_free (cf->a2); 00616 cf++; 00617 } 00618 g_free (vs->cfaces); 00619 00620 vs->ncf = g_slist_length (i); 00621 g_assert (vs->ncf > 0); 00622 cf = vs->cfaces = g_malloc (vs->ncf*sizeof (GtsSplitCFace)); 00623 #endif /* DYNAMIC_SPLIT */ 00624 #ifdef NEW 00625 while (i) { 00626 cf->f = i->data; 00627 g_assert (GTS_IS_FACE (cf->f)); 00628 GTS_OBJECT (cf->f)->klass = GTS_OBJECT_CLASS (cface_class ()); 00629 cf++; 00630 i = i->next; 00631 } 00632 i = e->triangles; 00633 cf = vs->cfaces; 00634 while (i) { 00635 cface_new (i->data, e, v1, v2, vs, heap, klass, cf); 00636 #ifdef DEBUG 00637 fprintf (stderr, "cface: %p->%d t: %p->%d a1: ", 00638 cf->f, id (cf->f), CFACE (cf->f)->t, id (CFACE (cf->f)->t)); 00639 { 00640 GtsTriangle * t, ** a; 00641 a = cf->a1; 00642 while ((t = *(a++))) 00643 fprintf (stderr, "%p->%d ", t, id (t)); 00644 fprintf (stderr, "a2: "); 00645 a = cf->a2; 00646 while ((t = *(a++))) 00647 fprintf (stderr, "%p->%d ", t, id (t)); 00648 fprintf (stderr, "\n"); 00649 } 00650 #endif 00651 cf++; 00652 i = i->next; 00653 } 00654 #else /* not NEW */ 00655 while (i) { 00656 cface_new (i->data, e, v1, v2, vs, heap 00657 #ifdef DYNAMIC_SPLIT 00658 , cf 00659 #endif /* DYNAMIC_SPLIT */ 00660 ); 00661 #ifdef DYNAMIC_SPLIT 00662 cf->f = i->data; 00663 cf++; 00664 #endif /* DYNAMIC_SPLIT */ 00665 i = i->next; 00666 } 00667 #endif /* NEW */ 00668 g_slist_free (e->triangles); 00669 e->triangles = NULL; 00670 gts_object_destroy (GTS_OBJECT (e)); 00671 00672 gts_allow_floating_vertices = FALSE; 00673 00674 end = NULL; 00675 i = v1->segments; 00676 while (i) { 00677 GtsSegment * s = i->data; 00678 if (s->v1 == v1) 00679 s->v1 = v; 00680 else 00681 s->v2 = v; 00682 end = i; 00683 i = i->next; 00684 } 00685 if (end) { 00686 end->next = v->segments; 00687 v->segments = v1->segments; 00688 v1->segments = NULL; 00689 } 00690 00691 end = NULL; 00692 i = v2->segments; 00693 while (i) { 00694 GtsSegment * s = i->data; 00695 if (s->v1 == v2) 00696 s->v1 = v; 00697 else 00698 s->v2 = v; 00699 end = i; 00700 i = i->next; 00701 } 00702 if (end) { 00703 end->next = v->segments; 00704 v->segments = v2->segments; 00705 v2->segments = NULL; 00706 } 00707 00708 #ifdef DEBUG 00709 if (invalid) { 00710 char fname[80]; 00711 FILE * fptr; 00712 GSList * triangles, * i; 00713 00714 sprintf (fname, "invalid_after.%d", ninvalid); 00715 fptr = fopen (fname, "wt"); 00716 triangles = gts_vertex_triangles (v, NULL); 00717 i = triangles; 00718 while (i) { 00719 GtsTriangle * t = i->data; 00720 fprintf (stderr, "checking %p->%d\n", t, id (t)); 00721 g_assert (GTS_IS_FACE (t)); 00722 gts_write_triangle (t, GTS_POINT (v), fptr); 00723 if (gts_triangle_is_duplicate (t)) 00724 fprintf (stderr, "%p->%d is duplicate\n", t, id (t)); 00725 if (gts_segment_is_duplicate (GTS_SEGMENT (t->e1))) 00726 fprintf (stderr, "e1 of %p->%d is duplicate\n", t, id (t)); 00727 if (gts_segment_is_duplicate (GTS_SEGMENT (t->e2))) 00728 fprintf (stderr, "e2 of %p->%d is duplicate\n", t, id (t)); 00729 if (gts_segment_is_duplicate (GTS_SEGMENT (t->e3))) 00730 fprintf (stderr, "e3 of %p->%d is duplicate\n", t, id (t)); 00731 i = i->next; 00732 } 00733 fclose (fptr); 00734 g_slist_free (triangles); 00735 #if 0 00736 gts_split_expand (vs, surface); 00737 00738 sprintf (fname, "invalid_after_after.%d", ninvalid); 00739 fptr = fopen (fname, "wt"); 00740 triangles = gts_vertex_triangles (v1, NULL); 00741 triangles = gts_vertex_triangles (v2, triangles); 00742 i = triangles; 00743 while (i) { 00744 GtsTriangle * t = i->data; 00745 gts_write_triangle (t, GTS_POINT (v), fptr); 00746 surface = GTS_FACE (t)->surfaces->data; 00747 if (gts_triangle_is_duplicate (t)) 00748 fprintf (stderr, "%p->%d is duplicate\n", t, id (t)); 00749 if (gts_segment_is_duplicate (GTS_SEGMENT (t->e1))) 00750 fprintf (stderr, "e1 of %p->%d is duplicate\n", t, id (t)); 00751 if (gts_segment_is_duplicate (GTS_SEGMENT (t->e2))) 00752 fprintf (stderr, "e2 of %p->%d is duplicate\n", t, id (t)); 00753 if (gts_segment_is_duplicate (GTS_SEGMENT (t->e3))) 00754 fprintf (stderr, "e3 of %p->%d is duplicate\n", t, id (t)); 00755 i = i->next; 00756 } 00757 fclose (fptr); 00758 g_slist_free (triangles); 00759 00760 exit (1); 00761 #endif 00762 ninvalid++; 00763 } 00764 #endif 00765 } 00766 00776 void gts_split_expand (GtsSplit * vs, 00777 GtsSurface * s, 00778 GtsEdgeClass * klass) 00779 { 00780 GSList * i; 00781 GtsEdge * e; 00782 GtsVertex * v, * v1, * v2; 00783 gboolean changed = FALSE; 00784 GtsSplitCFace * cf; 00785 guint j; 00786 00787 g_return_if_fail (vs != NULL); 00788 g_return_if_fail (s != NULL); 00789 g_return_if_fail (klass != NULL); 00790 00791 /* we don't want to destroy vertices */ 00792 gts_allow_floating_vertices = TRUE; 00793 00794 v1 = GTS_SPLIT_V1 (vs); 00795 v2 = GTS_SPLIT_V2 (vs); 00796 v = vs->v; 00797 #ifdef DEBUG_EXPAND 00798 fprintf (stderr, "expanding %p->%d: v1: %p->%d v2: %p->%d v: %p->%d\n", 00799 vs, id (vs), v1, id (v1), v2, id (v2), v, id (v)); 00800 #endif 00801 e = gts_edge_new (klass, v1, v2); 00802 cf = vs->cfaces; 00803 j = vs->ncf; 00804 while (j--) { 00805 cface_expand (CFACE (cf->f), cf->a1, cf->a2, e, v1, v2, v, klass); 00806 gts_surface_add_face (s, cf->f); 00807 cf++; 00808 } 00809 00810 gts_allow_floating_vertices = FALSE; 00811 00812 /* this part is described by figure "expand.fig" */ 00813 i = v->segments; 00814 while (i) { 00815 GtsEdge * e1 = i->data; 00816 GtsVertex * with = NULL; 00817 GSList * j = e1->triangles, * next = i->next; 00818 // fprintf (stderr, "e1: %p->%d\n", e1, id (e1)); 00819 while (j && !with) { 00820 with = GTS_OBJECT (j->data)->reserved; 00821 j = j->next; 00822 } 00823 if (with) { 00824 j = e1->triangles; 00825 while (j) { 00826 GtsTriangle * t = j->data; 00827 if (GTS_OBJECT (t)->reserved) { 00828 g_assert (GTS_OBJECT (t)->reserved == with); 00829 GTS_OBJECT (t)->reserved = NULL; 00830 } 00831 else 00832 GTS_OBJECT (t)->reserved = with; 00833 j = j->next; 00834 } 00835 if (GTS_SEGMENT (e1)->v1 == v) 00836 GTS_SEGMENT (e1)->v1 = with; 00837 else 00838 GTS_SEGMENT (e1)->v2 = with; 00839 00840 v->segments = g_slist_remove_link (v->segments, i); 00841 i->next = with->segments; 00842 with->segments = i; 00843 changed = TRUE; 00844 } 00845 if (next) 00846 i = next; 00847 else { 00848 /* check for infinite loop (the crossed out case in 00849 figure "expand.fig") */ 00850 g_assert (changed); 00851 changed = FALSE; 00852 i = v->segments; 00853 } 00854 } 00855 } 00856 00857 #ifndef DYNAMIC_SPLIT 00858 static void cface_neighbors (GtsSplitCFace * cf, 00859 GtsEdge * e, 00860 GtsVertex * v1, 00861 GtsVertex * v2) 00862 { 00863 GtsTriangle * t = GTS_TRIANGLE (cf->f), ** a; 00864 GtsEdge * e1 = t->e1, * e2 = t->e2, * e3 = t->e3; 00865 GSList * i; 00866 guint size; 00867 00868 ROTATE_ORIENT (e, e1, e2, e3); 00869 if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e1), v2)) { 00870 e3 = e1; e1 = e2; e2 = e3; 00871 } 00872 00873 i = e1->triangles; 00874 size = g_slist_length (i)*sizeof (GtsTriangle *); 00875 a = cf->a1 = g_malloc (size > 0 ? size : sizeof (GtsTriangle *)); 00876 while (i) { 00877 if (i->data != t) 00878 *(a++) = i->data; 00879 i = i->next; 00880 } 00881 *a = NULL; 00882 00883 i = e2->triangles; 00884 size = g_slist_length (i)*sizeof (GtsTriangle *); 00885 a = cf->a2 = g_malloc (size > 0 ? size : sizeof (GtsTriangle *)); 00886 while (i) { 00887 if (i->data != t) 00888 *(a++) = i->data; 00889 i = i->next; 00890 } 00891 *a = NULL; 00892 } 00893 #endif /*ifndef DYNAMIC_SPLIT */ 00894 00907 GtsSplit * gts_split_new (GtsSplitClass * klass, 00908 GtsVertex * v, 00909 GtsObject * o1, 00910 GtsObject * o2) 00911 { 00912 GtsSplit * vs; 00913 #ifndef DYNAMIC_SPLIT 00914 GtsVertex * v1, * v2; 00915 GtsEdge * e; 00916 GSList * i; 00917 GtsSplitCFace * cf; 00918 #endif 00919 00920 g_return_val_if_fail (klass != NULL, NULL); 00921 g_return_val_if_fail (v != NULL, NULL); 00922 g_return_val_if_fail (GTS_IS_SPLIT (o1) || GTS_IS_VERTEX (o1), NULL); 00923 g_return_val_if_fail (GTS_IS_SPLIT (o2) || GTS_IS_VERTEX (o2), NULL); 00924 00925 vs = GTS_SPLIT (gts_object_new (GTS_OBJECT_CLASS (klass))); 00926 vs->v = v; 00927 vs->v1 = o1; 00928 vs->v2 = o2; 00929 #ifdef DYNAMIC_SPLIT 00930 vs->ncf = 0; 00931 vs->cfaces = NULL; 00932 #else 00933 v1 = GTS_SPLIT_V1 (vs); 00934 v2 = GTS_SPLIT_V2 (vs); 00935 e = GTS_EDGE (gts_vertices_are_connected (v1, v2)); 00936 g_assert (e != NULL); 00937 i = e->triangles; 00938 vs->ncf = g_slist_length (i); 00939 g_assert (vs->ncf > 0); 00940 cf = vs->cfaces = g_malloc (vs->ncf*sizeof (GtsSplitCFace)); 00941 while (i) { 00942 cf->f = i->data; 00943 cface_neighbors (cf, e, v1, v2); 00944 i = i->next; 00945 cf++; 00946 } 00947 #endif 00948 00949 return vs; 00950 } 00951 00952 static gboolean 00953 split_traverse_pre_order (GtsSplit * vs, 00954 GtsSplitTraverseFunc func, 00955 gpointer data) 00956 { 00957 if (func (vs, data)) 00958 return TRUE; 00959 if (GTS_IS_SPLIT (vs->v1) && 00960 split_traverse_pre_order (GTS_SPLIT (vs->v1), func, data)) 00961 return TRUE; 00962 if (GTS_IS_SPLIT (vs->v2) && 00963 split_traverse_pre_order (GTS_SPLIT (vs->v2), func, data)) 00964 return TRUE; 00965 return FALSE; 00966 } 00967 00968 static gboolean 00969 split_depth_traverse_pre_order (GtsSplit * vs, 00970 guint depth, 00971 GtsSplitTraverseFunc func, 00972 gpointer data) 00973 { 00974 if (func (vs, data)) 00975 return TRUE; 00976 00977 depth--; 00978 if (!depth) 00979 return FALSE; 00980 00981 if (GTS_IS_SPLIT (vs->v1) && 00982 split_depth_traverse_pre_order (GTS_SPLIT (vs->v1), depth, func, data)) 00983 return TRUE; 00984 if (GTS_IS_SPLIT (vs->v2) && 00985 split_depth_traverse_pre_order (GTS_SPLIT (vs->v2), depth, func, data)) 00986 return TRUE; 00987 return FALSE; 00988 } 00989 00990 static gboolean 00991 split_traverse_post_order (GtsSplit * vs, 00992 GtsSplitTraverseFunc func, 00993 gpointer data) 00994 { 00995 if (GTS_IS_SPLIT (vs->v1) && 00996 split_traverse_post_order (GTS_SPLIT (vs->v1), func, data)) 00997 return TRUE; 00998 if (GTS_IS_SPLIT (vs->v2) && 00999 split_traverse_post_order (GTS_SPLIT (vs->v2), func, data)) 01000 return TRUE; 01001 if (func (vs, data)) 01002 return TRUE; 01003 return FALSE; 01004 } 01005 01006 static gboolean 01007 split_depth_traverse_post_order (GtsSplit * vs, 01008 guint depth, 01009 GtsSplitTraverseFunc func, 01010 gpointer data) 01011 { 01012 depth--; 01013 if (depth) { 01014 if (GTS_IS_SPLIT (vs->v1) && 01015 split_depth_traverse_post_order (GTS_SPLIT (vs->v1), 01016 depth, func, data)) 01017 return TRUE; 01018 if (GTS_IS_SPLIT (vs->v2) && 01019 split_depth_traverse_post_order (GTS_SPLIT (vs->v2), 01020 depth, func, data)) 01021 return TRUE; 01022 } 01023 if (func (vs, data)) 01024 return TRUE; 01025 return FALSE; 01026 } 01027 01045 void gts_split_traverse (GtsSplit * root, 01046 GTraverseType order, 01047 gint depth, 01048 GtsSplitTraverseFunc func, 01049 gpointer data) 01050 { 01051 g_return_if_fail (root != NULL); 01052 g_return_if_fail (func != NULL); 01053 g_return_if_fail (order < G_LEVEL_ORDER); 01054 g_return_if_fail (depth == -1 || depth > 0); 01055 01056 switch (order) { 01057 case G_PRE_ORDER: 01058 if (depth < 0) 01059 split_traverse_pre_order (root, func, data); 01060 else 01061 split_depth_traverse_pre_order (root, depth, func, data); 01062 break; 01063 case G_POST_ORDER: 01064 if (depth < 0) 01065 split_traverse_post_order (root, func, data); 01066 else 01067 split_depth_traverse_post_order (root, depth, func, data); 01068 break; 01069 default: 01070 g_assert_not_reached (); 01071 } 01072 } 01073 01080 guint gts_split_height (GtsSplit * root) 01081 { 01082 guint height = 0, tmp_height; 01083 01084 g_return_val_if_fail (root != NULL, 0); 01085 01086 if (GTS_IS_SPLIT (root->v1)) { 01087 tmp_height = gts_split_height (GTS_SPLIT (root->v1)); 01088 if (tmp_height > height) 01089 height = tmp_height; 01090 } 01091 if (GTS_IS_SPLIT (root->v2)) { 01092 tmp_height = gts_split_height (GTS_SPLIT (root->v2)); 01093 if (tmp_height > height) 01094 height = tmp_height; 01095 } 01096 01097 return height + 1; 01098 } 01099 01100 #ifndef DYNAMIC_SPLIT 01101 static gboolean list_array_are_identical (GSList * list, 01102 gpointer * array, 01103 gpointer excluded) 01104 { 01105 while (list) { 01106 gpointer data = list->data; 01107 if (data != excluded) { 01108 gboolean found = FALSE; 01109 gpointer * a = array; 01110 01111 while (!found && *a) 01112 if (*(a++) == data) 01113 found = TRUE; 01114 if (!found) 01115 return FALSE; 01116 } 01117 list = list->next; 01118 } 01119 return TRUE; 01120 } 01121 #endif /* ifndef DYNAMIC_SPLIT */ 01122 01123 #ifndef NEW 01124 gboolean gts_split_is_collapsable (GtsSplit * vs) 01125 { 01126 guint i; 01127 GtsSplitCFace * cf; 01128 GtsVertex * v1, * v2; 01129 GtsEdge * e; 01130 01131 g_return_val_if_fail (vs != NULL, FALSE); 01132 01133 v1 = GTS_SPLIT_V1 (vs); 01134 v2 = GTS_SPLIT_V2 (vs); 01135 g_return_val_if_fail ((e = GTS_EDGE (gts_vertices_are_connected (v1, v2))), 01136 FALSE); 01137 01138 #ifdef DYNAMIC_SPLIT 01139 if (!gts_edge_collapse_is_valid (e)) 01140 return FALSE; 01141 #else 01142 i = vs->ncf; 01143 cf = vs->cfaces; 01144 while (i--) { 01145 GtsTriangle * t = GTS_TRIANGLE (cf->f); 01146 GtsEdge * e1 = t->e1, * e2 = t->e2, * e3 = t->e3; 01147 01148 ROTATE_ORIENT (e, e1, e2, e3); 01149 if (SEGMENT_USE_VERTEX (GTS_SEGMENT (e1), v2)) { 01150 e3 = e1; e1 = e2; e2 = e3; 01151 } 01152 01153 if (!list_array_are_identical (e1->triangles, (gpointer *) cf->a1, t)) 01154 return FALSE; 01155 if (!list_array_are_identical (e2->triangles, (gpointer *) cf->a2, t)) 01156 return FALSE; 01157 01158 cf++; 01159 } 01160 #endif 01161 return TRUE; 01162 } 01163 #endif /* not NEW */ 01164 01165 #ifdef DEBUG_HEXPAND 01166 static guint expand_level = 0; 01167 01168 static void expand_indent (FILE * fptr) 01169 { 01170 guint i = expand_level; 01171 while (i--) 01172 fputc (' ', fptr); 01173 } 01174 #endif 01175 01184 void gts_hsplit_force_expand (GtsHSplit * hs, 01185 GtsHSurface * hsurface) 01186 { 01187 guint i; 01188 GtsSplitCFace * cf; 01189 01190 g_return_if_fail (hs != NULL); 01191 g_return_if_fail (hsurface != NULL); 01192 g_return_if_fail (hs->nchild == 0); 01193 01194 #ifdef DEBUG_HEXPAND 01195 expand_level += 2; 01196 #endif 01197 01198 if (hs->parent && hs->parent->nchild == 0) { 01199 #ifdef DEBUG_HEXPAND 01200 expand_indent (stderr); 01201 fprintf (stderr, "expand parent %p\n", hs->parent); 01202 #endif 01203 gts_hsplit_force_expand (hs->parent, hsurface); 01204 } 01205 01206 i = GTS_SPLIT (hs)->ncf; 01207 cf = GTS_SPLIT (hs)->cfaces; 01208 while (i--) { 01209 GtsTriangle ** j, * t; 01210 01211 j = cf->a1; 01212 while ((t = *(j++))) 01213 if (IS_CFACE (t)) { 01214 #ifdef DEBUG_HEXPAND 01215 expand_indent (stderr); 01216 fprintf (stderr, "expand a1: cf->f: %p t: %p parent_split: %p\n", 01217 cf->f, 01218 t, 01219 GTS_HSPLIT (CFACE (t)->parent_split)); 01220 #endif 01221 gts_hsplit_force_expand (GTS_HSPLIT (CFACE (t)->parent_split), 01222 hsurface); 01223 #ifdef DEBUG_HEXPAND 01224 g_assert (!IS_CFACE (t)); 01225 #endif 01226 } 01227 j = cf->a2; 01228 while ((t = *(j++))) 01229 if (IS_CFACE (t)) { 01230 #ifdef DEBUG_HEXPAND 01231 expand_indent (stderr); 01232 fprintf (stderr, "expand a2: cf->f: %p t: %p parent_split: %p\n", 01233 cf->f, 01234 t, 01235 GTS_HSPLIT (CFACE (t)->parent_split)); 01236 #endif 01237 gts_hsplit_force_expand (GTS_HSPLIT (CFACE (t)->parent_split), 01238 hsurface); 01239 } 01240 cf++; 01241 } 01242 01243 gts_hsplit_expand (hs, hsurface); 01244 01245 #ifdef DEBUG_HEXPAND 01246 expand_level -= 2; 01247 expand_indent (stderr); 01248 fprintf (stderr, "%p expanded\n", hs); 01249 #endif 01250 } 01251 01252 static void index_object (GtsObject * o, guint * n) 01253 { 01254 o->reserved = GUINT_TO_POINTER ((*n)++); 01255 } 01256 01257 static void index_face (GtsFace * f, gpointer * data) 01258 { 01259 guint * nf = data[1]; 01260 01261 g_hash_table_insert (data[0], f, GUINT_TO_POINTER ((*nf)++)); 01262 } 01263 01271 void gts_psurface_write (GtsPSurface * ps, FILE * fptr) 01272 { 01273 guint nv = 1; 01274 guint nf = 1; 01275 GHashTable * hash; 01276 gpointer data[2]; 01277 01278 g_return_if_fail (ps != NULL); 01279 g_return_if_fail (fptr != NULL); 01280 g_return_if_fail (GTS_PSURFACE_IS_CLOSED (ps)); 01281 01282 while (gts_psurface_remove_vertex (ps)) 01283 ; 01284 01285 GTS_POINT_CLASS (ps->s->vertex_class)->binary = FALSE; 01286 gts_surface_write (ps->s, fptr); 01287 01288 gts_surface_foreach_vertex (ps->s, (GtsFunc) index_object, &nv); 01289 hash = g_hash_table_new (NULL, NULL); 01290 data[0] = hash; 01291 data[1] = &nf; 01292 gts_surface_foreach_face (ps->s, (GtsFunc) index_face, data); 01293 01294 fprintf (fptr, "%u\n", ps->split->len); 01295 while (ps->pos) { 01296 GtsSplit * vs = g_ptr_array_index (ps->split, --ps->pos); 01297 GtsSplitCFace * scf = vs->cfaces; 01298 GtsVertex * v1, * v2; 01299 guint i = vs->ncf; 01300 01301 fprintf (fptr, "%u %u", 01302 GPOINTER_TO_UINT (GTS_OBJECT (vs->v)->reserved), 01303 vs->ncf); 01304 if (GTS_OBJECT (vs)->klass->write) 01305 (*GTS_OBJECT (vs)->klass->write) (GTS_OBJECT (vs), fptr); 01306 fputc ('\n', fptr); 01307 01308 v1 = GTS_IS_SPLIT (vs->v1) ? GTS_SPLIT (vs->v1)->v : GTS_VERTEX (vs->v1); 01309 GTS_OBJECT (v1)->reserved = GUINT_TO_POINTER (nv++); 01310 v2 = GTS_IS_SPLIT (vs->v2) ? GTS_SPLIT (vs->v2)->v : GTS_VERTEX (vs->v2); 01311 GTS_OBJECT (v2)->reserved = GUINT_TO_POINTER (nv++); 01312 01313 (*GTS_OBJECT (v1)->klass->write) (GTS_OBJECT (v1), fptr); 01314 fputc ('\n', fptr); 01315 01316 (*GTS_OBJECT (v2)->klass->write) (GTS_OBJECT (v2), fptr); 01317 fputc ('\n', fptr); 01318 01319 while (i--) { 01320 CFace * cf = CFACE (scf->f); 01321 GtsTriangle ** a, * t; 01322 01323 fprintf (fptr, "%u %u", 01324 GPOINTER_TO_UINT (g_hash_table_lookup (hash, cf->t)), 01325 cf->flags); 01326 if (GTS_OBJECT_CLASS (ps->s->face_class)->write) 01327 (*GTS_OBJECT_CLASS (ps->s->face_class)->write) (GTS_OBJECT (cf), fptr); 01328 fputc ('\n', fptr); 01329 01330 a = scf->a1; 01331 while ((t = *(a++))) 01332 fprintf (fptr, "%u ", 01333 GPOINTER_TO_UINT (g_hash_table_lookup (hash, t))); 01334 fprintf (fptr, "\n"); 01335 01336 a = scf->a2; 01337 while ((t = *(a++))) 01338 fprintf (fptr, "%u ", 01339 GPOINTER_TO_UINT (g_hash_table_lookup (hash, t))); 01340 fprintf (fptr, "\n"); 01341 01342 g_hash_table_insert (hash, cf, GUINT_TO_POINTER (nf++)); 01343 01344 scf++; 01345 } 01346 01347 gts_split_expand (vs, ps->s, ps->s->edge_class); 01348 } 01349 01350 gts_surface_foreach_vertex (ps->s, 01351 (GtsFunc) gts_object_reset_reserved, NULL); 01352 g_hash_table_destroy (hash); 01353 } 01354 01355 static guint surface_read (GtsSurface * surface, 01356 GtsFile * f, 01357 GPtrArray * vertices, 01358 GPtrArray * faces) 01359 { 01360 GtsEdge ** edges; 01361 guint n, nv, ne, nf; 01362 01363 g_return_val_if_fail (surface != NULL, 1); 01364 g_return_val_if_fail (f != NULL, 1); 01365 01366 if (f->type != GTS_INT) { 01367 gts_file_error (f, "expecting an integer (number of vertices)"); 01368 return f->line; 01369 } 01370 nv = atoi (f->token->str); 01371 01372 gts_file_next_token (f); 01373 if (f->type != GTS_INT) { 01374 gts_file_error (f, "expecting an integer (number of edges)"); 01375 return f->line; 01376 } 01377 ne = atoi (f->token->str); 01378 01379 gts_file_next_token (f); 01380 if (f->type != GTS_INT) { 01381 gts_file_error (f, "expecting an integer (number of faces)"); 01382 return f->line; 01383 } 01384 nf = atoi (f->token->str); 01385 01386 gts_file_next_token (f); 01387 if (f->type == GTS_STRING) { 01388 if (f->type != GTS_STRING) { 01389 gts_file_error (f, "expecting a string (GtsSurfaceClass)"); 01390 return f->line; 01391 } 01392 gts_file_next_token (f); 01393 if (f->type != GTS_STRING) { 01394 gts_file_error (f, "expecting a string (GtsFaceClass)"); 01395 return f->line; 01396 } 01397 gts_file_next_token (f); 01398 if (f->type != GTS_STRING) { 01399 gts_file_error (f, "expecting a string (GtsEdgeClass)"); 01400 return f->line; 01401 } 01402 gts_file_next_token (f); 01403 if (f->type != GTS_STRING) { 01404 gts_file_error (f, "expecting a string (GtsVertexClass)"); 01405 return f->line; 01406 } 01407 if (!strcmp (f->token->str, "GtsVertexBinary")) 01408 GTS_POINT_CLASS (surface->vertex_class)->binary = TRUE; 01409 else 01410 gts_file_first_token_after (f, '\n'); 01411 } 01412 else 01413 gts_file_first_token_after (f, '\n'); 01414 01415 g_ptr_array_set_size (vertices, nv); 01416 g_ptr_array_set_size (faces, nf); 01417 /* allocate nv + 1 just in case nv == 0 */ 01418 edges = g_malloc ((ne + 1)*sizeof (GtsEdge *)); 01419 01420 n = 0; 01421 while (n < nv && f->type != GTS_ERROR) { 01422 GtsObject * new_vertex = 01423 gts_object_new (GTS_OBJECT_CLASS (surface->vertex_class)); 01424 01425 (* GTS_OBJECT_CLASS (surface->vertex_class)->read) (&new_vertex, f); 01426 if (f->type != GTS_ERROR) { 01427 if (!GTS_POINT_CLASS (surface->vertex_class)->binary) 01428 gts_file_first_token_after (f, '\n'); 01429 g_ptr_array_index (vertices, n++) = new_vertex; 01430 } 01431 else 01432 gts_object_destroy (new_vertex); 01433 } 01434 if (f->type == GTS_ERROR) 01435 nv = n; 01436 if (GTS_POINT_CLASS (surface->vertex_class)->binary) 01437 gts_file_first_token_after (f, '\n'); 01438 01439 n = 0; 01440 while (n < ne && f->type != GTS_ERROR) { 01441 guint p1, p2; 01442 01443 if (f->type != GTS_INT) 01444 gts_file_error (f, "expecting an integer (first vertex index)"); 01445 else { 01446 p1 = atoi (f->token->str); 01447 if (p1 == 0 || p1 > nv) 01448 gts_file_error (f, "vertex index `%d' is out of range `[1,%d]'", 01449 p1, nv); 01450 else { 01451 gts_file_next_token (f); 01452 if (f->type != GTS_INT) 01453 gts_file_error (f, "expecting an integer (second vertex index)"); 01454 else { 01455 p2 = atoi (f->token->str); 01456 if (p2 == 0 || p2 > nv) 01457 gts_file_error (f, "vertex index `%d' is out of range `[1,%d]'", 01458 p2, nv); 01459 else { 01460 GtsEdge * new_edge = 01461 gts_edge_new (surface->edge_class, 01462 g_ptr_array_index (vertices, p1 - 1), 01463 g_ptr_array_index (vertices, p2 - 1)); 01464 01465 gts_file_next_token (f); 01466 if (f->type != '\n') 01467 if (GTS_OBJECT_CLASS (surface->edge_class)->read) 01468 (*GTS_OBJECT_CLASS (surface->edge_class)->read) 01469 ((GtsObject **) &new_edge, f); 01470 gts_file_first_token_after (f, '\n'); 01471 edges[n++] = new_edge; 01472 } 01473 } 01474 } 01475 } 01476 } 01477 if (f->type == GTS_ERROR) 01478 ne = n; 01479 01480 n = 0; 01481 while (n < nf && f->type != GTS_ERROR) { 01482 guint s1, s2, s3; 01483 01484 if (f->type != GTS_INT) 01485 gts_file_error (f, "expecting an integer (first edge index)"); 01486 else { 01487 s1 = atoi (f->token->str); 01488 if (s1 == 0 || s1 > ne) 01489 gts_file_error (f, "edge index `%d' is out of range `[1,%d]'", 01490 s1, ne); 01491 else { 01492 gts_file_next_token (f); 01493 if (f->type != GTS_INT) 01494 gts_file_error (f, "expecting an integer (second edge index)"); 01495 else { 01496 s2 = atoi (f->token->str); 01497 if (s2 == 0 || s2 > ne) 01498 gts_file_error (f, "edge index `%d' is out of range `[1,%d]'", 01499 s2, ne); 01500 else { 01501 gts_file_next_token (f); 01502 if (f->type != GTS_INT) 01503 gts_file_error (f, "expecting an integer (third edge index)"); 01504 else { 01505 s3 = atoi (f->token->str); 01506 if (s3 == 0 || s3 > ne) 01507 gts_file_error (f, "edge index `%d' is out of range `[1,%d]'", 01508 s3, ne); 01509 else { 01510 GtsFace * new_face = gts_face_new (surface->face_class, 01511 edges[s1 - 1], 01512 edges[s2 - 1], 01513 edges[s3 - 1]); 01514 01515 gts_file_next_token (f); 01516 if (f->type != '\n') 01517 if (GTS_OBJECT_CLASS (surface->face_class)->read) 01518 (*GTS_OBJECT_CLASS (surface->face_class)->read) 01519 ((GtsObject **) &new_face, f); 01520 gts_file_first_token_after (f, '\n'); 01521 gts_surface_add_face (surface, new_face); 01522 g_ptr_array_index (faces, n++) = new_face; 01523 } 01524 } 01525 } 01526 } 01527 } 01528 } 01529 } 01530 01531 g_free (edges); 01532 01533 if (f->type == GTS_ERROR) { 01534 gts_allow_floating_vertices = TRUE; 01535 while (nv) 01536 gts_object_destroy (GTS_OBJECT (g_ptr_array_index (vertices, nv-- - 1))); 01537 gts_allow_floating_vertices = FALSE; 01538 return f->line; 01539 } 01540 01541 return 0; 01542 } 01543 01563 GtsPSurface * gts_psurface_open (GtsPSurfaceClass * klass, 01564 GtsSurface * s, 01565 GtsSplitClass * split_class, 01566 GtsFile * f) 01567 { 01568 GtsPSurface * ps; 01569 01570 g_return_val_if_fail (klass != NULL, NULL); 01571 g_return_val_if_fail (s != NULL, NULL); 01572 g_return_val_if_fail (split_class != NULL, NULL); 01573 g_return_val_if_fail (f != NULL, NULL); 01574 01575 ps = GTS_PSURFACE (gts_object_new (GTS_OBJECT_CLASS (klass))); 01576 ps->s = s; 01577 ps->split_class = split_class; 01578 01579 ps->vertices = g_ptr_array_new (); 01580 ps->faces = g_ptr_array_new (); 01581 01582 if (surface_read (s, f, ps->vertices, ps->faces)) { 01583 ps->s = NULL; 01584 gts_object_destroy (GTS_OBJECT (ps)); 01585 return NULL; 01586 } 01587 01588 ps->min = gts_surface_vertex_number (ps->s); 01589 ps->pos = 0; 01590 01591 if (f->type == GTS_INT) { 01592 gint ns = atoi (f->token->str); 01593 01594 if (ns > 0) { 01595 g_ptr_array_set_size (ps->split, ns); 01596 gts_file_first_token_after (f, '\n'); 01597 } 01598 } 01599 01600 return ps; 01601 } 01602 01615 GtsSplit * gts_psurface_read_vertex (GtsPSurface * ps, GtsFile * fp) 01616 { 01617 guint nv, ncf; 01618 GtsSplit * vs, * parent; 01619 GtsSplitCFace * scf; 01620 01621 g_return_val_if_fail (ps != NULL, NULL); 01622 g_return_val_if_fail (fp != NULL, NULL); 01623 g_return_val_if_fail (!GTS_PSURFACE_IS_CLOSED (ps), NULL); 01624 01625 if (ps->pos >= ps->split->len) 01626 return NULL; 01627 01628 if (fp->type == GTS_NONE) 01629 return NULL; 01630 if (fp->type != GTS_INT) { 01631 gts_file_error (fp, "expecting an integer (vertex index)"); 01632 return NULL; 01633 } 01634 nv = atoi (fp->token->str); 01635 if (nv == 0 || nv > ps->vertices->len) { 01636 gts_file_error (fp, "vertex index `%d' is out of range `[1,%d]'", 01637 nv, ps->vertices->len); 01638 return NULL; 01639 } 01640 01641 gts_file_next_token (fp); 01642 if (fp->type != GTS_INT) { 01643 gts_file_error (fp, "expecting an integer (ncf)"); 01644 return NULL; 01645 } 01646 ncf = atoi (fp->token->str); 01647 01648 vs = GTS_SPLIT (gts_object_new (GTS_OBJECT_CLASS (ps->split_class))); 01649 01650 vs->v = g_ptr_array_index (ps->vertices, nv - 1); 01651 vs->v1 = vs->v2 = NULL; 01652 vs->cfaces = NULL; 01653 vs->ncf = 0; 01654 01655 gts_file_next_token (fp); 01656 if (fp->type != '\n') 01657 if (GTS_OBJECT (vs)->klass->read) 01658 (* GTS_OBJECT (vs)->klass->read) ((GtsObject **) &vs, fp); 01659 gts_file_first_token_after (fp, '\n'); 01660 01661 if (fp->type != GTS_ERROR) { 01662 vs->v1 = gts_object_new (GTS_OBJECT_CLASS (ps->s->vertex_class)); 01663 (* GTS_OBJECT_CLASS (ps->s->vertex_class)->read) (&(vs->v1), fp); 01664 if (fp->type != GTS_ERROR) { 01665 vs->v1->reserved = vs; 01666 g_ptr_array_add (ps->vertices, vs->v1); 01667 01668 gts_file_first_token_after (fp, '\n'); 01669 01670 vs->v2 = gts_object_new (GTS_OBJECT_CLASS (ps->s->vertex_class)); 01671 (*GTS_OBJECT_CLASS (ps->s->vertex_class)->read) (&(vs->v2), fp); 01672 if (fp->type != GTS_ERROR) { 01673 vs->v2->reserved = vs; 01674 g_ptr_array_add (ps->vertices, vs->v2); 01675 gts_file_first_token_after (fp, '\n'); 01676 } 01677 } 01678 } 01679 01680 if (fp->type != GTS_ERROR) { 01681 scf = vs->cfaces = g_malloc (sizeof (GtsSplitCFace)*ncf); 01682 while (fp->type != GTS_ERROR && ncf--) { 01683 guint it, flags; 01684 GtsFace * f; 01685 CFace * cf; 01686 GPtrArray * a; 01687 01688 if (fp->type != GTS_INT) 01689 gts_file_error (fp, "expecting an integer (face index)"); 01690 else { 01691 it = atoi (fp->token->str); 01692 if (it == 0 || it > ps->faces->len) 01693 gts_file_error (fp, "face index `%d' is out of range `[1,%d]'", 01694 it, ps->faces->len); 01695 else { 01696 gts_file_next_token (fp); 01697 if (fp->type != GTS_INT) 01698 gts_file_error (fp, "expecting an integer (flags)"); 01699 else { 01700 flags = atoi (fp->token->str); 01701 f = 01702 GTS_FACE (gts_object_new (GTS_OBJECT_CLASS (ps->s->face_class))); 01703 01704 gts_file_next_token (fp); 01705 if (fp->type != '\n') 01706 if (GTS_OBJECT (f)->klass->read) 01707 (*GTS_OBJECT (f)->klass->read) ((GtsObject **) &f, fp); 01708 gts_file_first_token_after (fp, '\n'); 01709 if (fp->type != GTS_ERROR) { 01710 scf->f = f; 01711 01712 cf = (CFace *) f; 01713 GTS_OBJECT (cf)->klass = GTS_OBJECT_CLASS (cface_class ()); 01714 cf->parent_split = vs; 01715 cf->t = g_ptr_array_index (ps->faces, it - 1); 01716 cf->flags = flags; 01717 01718 a = g_ptr_array_new (); 01719 do { 01720 if (fp->type != GTS_INT) 01721 gts_file_error (fp, "expecting an integer (face index)"); 01722 else { 01723 it = atoi (fp->token->str); 01724 if (it > ps->faces->len) 01725 gts_file_error (fp, 01726 "face index `%d' is out of range `[1,%d]'", 01727 it, ps->faces->len); 01728 else { 01729 g_ptr_array_add (a, g_ptr_array_index (ps->faces, 01730 it - 1)); 01731 gts_file_next_token (fp); 01732 } 01733 } 01734 } while (fp->type != GTS_ERROR && fp->type != '\n'); 01735 gts_file_first_token_after (fp, '\n'); 01736 g_ptr_array_add (a, NULL); 01737 scf->a1 = (GtsTriangle **) a->pdata; 01738 g_ptr_array_free (a, FALSE); 01739 01740 if (fp->type != GTS_ERROR) { 01741 a = g_ptr_array_new (); 01742 do { 01743 if (fp->type != GTS_INT) 01744 gts_file_error (fp, "expecting an integer (face index)"); 01745 else { 01746 it = atoi (fp->token->str); 01747 if (it > ps->faces->len) 01748 gts_file_error (fp, 01749 "face index `%d' is out of range `[1,%d]'", 01750 it, ps->faces->len); 01751 else { 01752 g_ptr_array_add (a, g_ptr_array_index (ps->faces, 01753 it - 1)); 01754 gts_file_next_token (fp); 01755 } 01756 } 01757 } while (fp->type != GTS_ERROR && fp->type != '\n'); 01758 gts_file_first_token_after (fp, '\n'); 01759 g_ptr_array_add (a, NULL); 01760 scf->a2 = (GtsTriangle **) a->pdata; 01761 g_ptr_array_free (a, FALSE); 01762 01763 g_ptr_array_add (ps->faces, f); 01764 01765 vs->ncf++; 01766 scf++; 01767 } 01768 } 01769 } 01770 } 01771 } 01772 } 01773 } 01774 01775 if (fp->type != GTS_ERROR) { 01776 if ((parent = GTS_OBJECT (vs->v)->reserved)) { 01777 GTS_OBJECT (vs->v)->reserved = NULL; 01778 if (parent->v1 == GTS_OBJECT (vs->v)) 01779 parent->v1 = GTS_OBJECT (vs); 01780 else { 01781 g_assert (parent->v2 == GTS_OBJECT (vs->v)); 01782 parent->v2 = GTS_OBJECT (vs); 01783 } 01784 } 01785 g_ptr_array_index (ps->split, ps->pos++) = vs; 01786 gts_split_expand (vs, ps->s, ps->s->edge_class); 01787 01788 return vs; 01789 } 01790 01791 if (vs->v1) gts_object_destroy (vs->v1); 01792 if (vs->v2) gts_object_destroy (vs->v2); 01793 gts_object_destroy (GTS_OBJECT (vs)); 01794 01795 return NULL; 01796 } 01797 01804 void gts_psurface_close (GtsPSurface * ps) 01805 { 01806 g_return_if_fail (ps != NULL); 01807 g_return_if_fail (!GTS_PSURFACE_IS_CLOSED (ps)); 01808 01809 g_ptr_array_free (ps->vertices, TRUE); 01810 g_ptr_array_free (ps->faces, TRUE); 01811 ps->faces = ps->vertices = NULL; 01812 01813 gts_surface_foreach_vertex (ps->s, 01814 (GtsFunc) gts_object_reset_reserved, NULL); 01815 if (ps->pos > 0) 01816 g_ptr_array_set_size (ps->split, ps->pos); 01817 if (ps->split->len > 1) { 01818 guint i, half = ps->split->len/2, n = ps->split->len - 1; 01819 01820 for (i = 0; i < half; i++) { 01821 gpointer p1 = g_ptr_array_index (ps->split, i); 01822 gpointer p2 = g_ptr_array_index (ps->split, n - i); 01823 g_ptr_array_index (ps->split, n - i) = p1; 01824 g_ptr_array_index (ps->split, i) = p2; 01825 } 01826 } 01827 ps->pos = 0; 01828 }