pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 /* GTS - Library for the manipulation of triangulated surfaces 00002 * Copyright (C) 1999-2003 Wagner Toledo Correa, 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 #define PRINT_HEAP_ELEMENTS 0 00023 00024 typedef struct { 00025 GtsTriangle * t; 00026 gboolean used; 00027 GSList * neighbors; 00028 GtsEHeapPair *pos; 00029 } tri_data_t; 00030 00031 typedef struct { 00032 GHashTable * ht; 00033 } map_t; 00034 00035 typedef struct { 00036 map_t * map; 00037 GtsEHeap * heap; 00038 } heap_t; 00039 00040 static tri_data_t * tri_data_new (GtsTriangle * t); 00041 static void tri_data_destroy (tri_data_t * td); 00042 static guint tri_data_num_unused_neighbors2 (const tri_data_t * td, 00043 const map_t * map); 00044 static GHashTable * tri_data_unused_neighbors2 (const tri_data_t * td, 00045 const map_t * map); 00046 00047 static map_t * map_new (GtsSurface * s); 00048 static void map_destroy (map_t * map); 00049 static tri_data_t * map_lookup (const map_t * map, GtsTriangle * t); 00050 00051 00052 static heap_t * heap_new (GtsSurface * s); 00053 static void heap_destroy (heap_t * heap); 00054 static gboolean heap_is_empty (const heap_t * heap); 00055 static GtsTriangle * heap_top (const heap_t * heap); 00056 static void heap_remove (heap_t * heap, GtsTriangle * t); 00057 00058 /* helper functions */ 00059 00060 static gboolean vertices_are_unique (GtsVertex * v1, 00061 GtsVertex * v2, 00062 GtsVertex * v3) 00063 { 00064 g_assert (v1 && v2 && v3); 00065 return (v1 != v2 && v1 != v3 && v2 != v3); 00066 } 00067 00068 static gboolean vertex_is_one_of (GtsVertex * v, 00069 GtsVertex * v1, 00070 GtsVertex * v2, 00071 GtsVertex * v3) 00072 { 00073 g_assert (v && v1 && v2 && v3); 00074 return v == v1 || v == v2 || v == v3; 00075 } 00076 00077 static guint num_shared_vertices (GtsVertex * u1, 00078 GtsVertex * u2, 00079 GtsVertex * u3, 00080 GtsVertex * v1, 00081 GtsVertex * v2, 00082 GtsVertex * v3) 00083 { 00084 guint n = 0; 00085 00086 g_assert (u1 && u2 && u3); 00087 g_assert (v1 && v2 && v3); 00088 g_assert (vertices_are_unique (u1, u2, u3)); 00089 g_assert (vertices_are_unique (v1, v2, v3)); 00090 00091 if (vertex_is_one_of (v1, u1, u2, u3)) 00092 n++; 00093 if (vertex_is_one_of (v2, u1, u2, u3)) 00094 n++; 00095 if (vertex_is_one_of (v3, u1, u2, u3)) 00096 n++; 00097 return n; 00098 } 00099 00100 static gboolean vertices_match (GtsVertex * v1, 00101 GtsVertex * v2, 00102 GtsVertex * v3, 00103 GtsVertex ** v4, 00104 GtsVertex ** v5, 00105 GtsVertex ** v6) 00106 { 00107 guint i; 00108 00109 g_assert (v4 && v5 && v6); 00110 g_assert (*v4 && *v5 && *v6); 00111 g_assert (vertices_are_unique (*v4, *v5, *v6)); 00112 00113 for (i = 0; i < 2; i++) { 00114 if ((!v1 || (v1 == *v4)) && 00115 (!v2 || (v2 == *v5)) && 00116 (!v3 || (v3 == *v6))) 00117 return TRUE; 00118 else { 00119 GtsVertex * v7 = * v4; 00120 00121 *v4 = *v5; 00122 *v5 = *v6; 00123 *v6 = v7; 00124 } 00125 } 00126 return ((!v1 || (v1 == *v4)) && 00127 (!v2 || (v2 == *v5)) && 00128 (!v3 || (v3 == *v6))); 00129 } 00130 00131 static GtsVertex * non_shared_vertex1 (GtsVertex * u1, 00132 GtsVertex * u2, 00133 GtsVertex * u3, 00134 GtsVertex * v1, 00135 GtsVertex * v2, 00136 GtsVertex * v3) 00137 { 00138 GtsVertex * u = NULL; 00139 00140 g_assert (u1 && u2 && u3); 00141 g_assert (v1 && v2 && v3); 00142 g_assert (vertices_are_unique (u1, u2, u3)); 00143 g_assert (vertices_are_unique (v1, v2, v3)); 00144 g_assert (num_shared_vertices (u1, u2, u3, v1, v2, v3) == 2); 00145 00146 if (!vertex_is_one_of (u1, v1, v2, v3)) { 00147 g_assert (vertex_is_one_of (u2, v1, v2, v3)); 00148 g_assert (vertex_is_one_of (u3, v1, v2, v3)); 00149 u = u1; 00150 } else if (!vertex_is_one_of (u2, v1, v2, v3)) { 00151 g_assert (vertex_is_one_of (u1, v1, v2, v3)); 00152 g_assert (vertex_is_one_of (u3, v1, v2, v3)); 00153 u = u2; 00154 } else if (!vertex_is_one_of (u3, v1, v2, v3)) { 00155 g_assert (vertex_is_one_of (u1, v1, v2, v3)); 00156 g_assert (vertex_is_one_of (u2, v1, v2, v3)); 00157 u = u3; 00158 } else 00159 g_assert_not_reached (); 00160 00161 return u; 00162 } 00163 00164 static void match_vertex (GtsVertex * v, 00165 GtsVertex ** v1, 00166 GtsVertex ** v2, 00167 GtsVertex ** v3) 00168 { 00169 g_assert (v && v1 && v2 && v3); 00170 g_assert (*v1 && *v2 && *v3); 00171 g_assert (vertex_is_one_of (v, *v1, *v2, *v3)); 00172 while (*v1 != v) { 00173 GtsVertex *v0 = *v1; 00174 00175 *v1 = *v2; 00176 *v2 = *v3; 00177 *v3 = v0; 00178 } 00179 } 00180 00181 /* tri_data_t functions */ 00182 00183 static tri_data_t * tri_data_new (GtsTriangle * t) 00184 { 00185 tri_data_t * td; 00186 00187 td = g_malloc (sizeof (tri_data_t)); 00188 td->t = t; 00189 td->used = FALSE; 00190 td->neighbors = gts_triangle_neighbors (t); 00191 td->pos = NULL; 00192 00193 return td; 00194 } 00195 00196 static void tri_data_destroy (tri_data_t * td) 00197 { 00198 if (!td) 00199 return; 00200 g_slist_free (td->neighbors); 00201 g_free (td); 00202 } 00203 00204 static guint tri_data_num_unused_neighbors2 (const tri_data_t * td, 00205 const map_t * map) 00206 { 00207 GHashTable *h; 00208 guint n; 00209 00210 g_assert (td); 00211 g_assert (map); 00212 h = tri_data_unused_neighbors2 (td, map); 00213 n = g_hash_table_size (h); 00214 g_hash_table_destroy (h); 00215 return n; 00216 } 00217 00218 static void copy_key_to_array (gpointer key, 00219 gpointer value, 00220 gpointer user_data) 00221 { 00222 GtsTriangle * t = key; 00223 GtsTriangle *** p = user_data; 00224 00225 (void) value; 00226 g_assert (t); 00227 g_assert (p && *p); 00228 **p = t; 00229 (*p)++; 00230 } 00231 00232 static gboolean are_neighbors_unique (GHashTable *h) 00233 { 00234 GtsTriangle ** a; 00235 GtsTriangle ** p; 00236 gint i, j, n; /* guint won't work if n == 0 */ 00237 00238 g_assert (h); 00239 n = g_hash_table_size (h); 00240 #ifdef DEBUG 00241 if (n > 9) 00242 g_warning ("triangle has %d 2-level neighbors", n); 00243 #endif /* DEBUG */ 00244 a = g_malloc(n*sizeof (GtsTriangle *)); 00245 p = a; 00246 g_hash_table_foreach (h, copy_key_to_array, &p); 00247 for (i = 0; i < n - 1; i++) { 00248 g_assert (a[i]); 00249 for (j = i + 1; j < n; j++) { 00250 g_assert (a[j]); 00251 if (a[i] == a[j]) { 00252 g_free (a); 00253 return FALSE; 00254 } 00255 } 00256 } 00257 g_free (a); 00258 return TRUE; 00259 } 00260 00261 static GHashTable * tri_data_unused_neighbors2 (const tri_data_t * td, 00262 const map_t * map) 00263 { 00264 GHashTable * h = g_hash_table_new (NULL, NULL); 00265 GSList * li; 00266 00267 g_assert (td); 00268 g_assert (map); 00269 for (li = td->neighbors; li != NULL; li = li->next) { 00270 GtsTriangle * t2 = li->data; 00271 tri_data_t * td2 = map_lookup (map, t2); 00272 GSList * lj; 00273 00274 g_assert (td2); 00275 if (!td2->used) { 00276 g_hash_table_insert (h, t2, td2); 00277 for (lj = td2->neighbors; lj != NULL; lj = lj->next) { 00278 GtsTriangle * t3 = lj->data; 00279 tri_data_t * td3 = map_lookup (map, t3); 00280 00281 g_assert (td3); 00282 if (td3 != td && !td3->used) 00283 g_hash_table_insert (h, t3, td3); 00284 } 00285 } 00286 } 00287 g_assert (are_neighbors_unique (h)); 00288 return h; 00289 } 00290 00291 #if PRINT_HEAP_ELEMENTS 00292 static void tri_data_print (const tri_data_t * td, FILE * fp) 00293 { 00294 g_assert (td); 00295 g_assert (fp); 00296 fprintf(fp, "td=%p t=%p used=%d pos=%p key=%f\n", 00297 td, td->t, td->used, td->pos, 00298 td->pos ? td->pos->key : -1.0); 00299 } 00300 #endif /* PRINT_HEAP_ELEMENTS */ 00301 00302 /* heap_t functions */ 00303 00304 static gdouble triangle_priority (gpointer item, gpointer data) 00305 { 00306 GtsTriangle * t = item; 00307 map_t * map = data; 00308 tri_data_t * td; 00309 gdouble k; 00310 00311 g_assert (t); 00312 g_assert (map); 00313 td = map_lookup (map, t); 00314 g_assert (td); 00315 k = tri_data_num_unused_neighbors2 (td, map); 00316 return k; 00317 } 00318 00319 #if PRINT_HEAP_ELEMENTS 00320 static void print_heap_element (gpointer data, gpointer user_data) 00321 { 00322 GtsTriangle * t = data; 00323 map_t * map = user_data; 00324 tri_data_t * td; 00325 00326 g_assert (t); 00327 g_assert (map); 00328 td = map_lookup (map, t); 00329 g_assert (td); 00330 g_assert (!td->used); 00331 g_assert (td->pos); 00332 tri_data_print (td, stderr); 00333 } 00334 #endif /* PRINT_HEAP_ELEMENTS */ 00335 00336 static void insert_entry_into_heap (gpointer key, 00337 gpointer value, 00338 gpointer user_data) 00339 { 00340 GtsTriangle * t = key; 00341 tri_data_t * td = value; 00342 GtsEHeap * heap = user_data; 00343 00344 g_assert (!td->pos); 00345 td->pos = gts_eheap_insert (heap, t); 00346 g_assert (td->pos); 00347 } 00348 00349 static heap_t * heap_new (GtsSurface *s) 00350 { 00351 heap_t * heap; 00352 00353 g_assert (s); 00354 heap = g_malloc (sizeof (heap_t)); 00355 heap->map = map_new (s); 00356 heap->heap = gts_eheap_new (triangle_priority, heap->map); 00357 g_hash_table_foreach (heap->map->ht, 00358 insert_entry_into_heap, 00359 heap->heap); 00360 #if PRINT_HEAP_ELEMENTS 00361 gts_eheap_foreach (heap->heap, print_heap_element, heap->map); 00362 #endif /* PRINT_HEAP_ELEMENTS */ 00363 return heap; 00364 } 00365 00366 static void heap_destroy (heap_t * heap) 00367 { 00368 if (!heap) 00369 return; 00370 map_destroy (heap->map); 00371 gts_eheap_destroy (heap->heap); 00372 g_free (heap); 00373 } 00374 00375 static gboolean heap_is_empty (const heap_t * heap) 00376 { 00377 g_assert (heap); 00378 g_assert (heap->heap); 00379 return gts_eheap_size (heap->heap) == 0; 00380 } 00381 00382 typedef struct { 00383 const heap_t * heap; 00384 double min_key; 00385 } min_key_t; 00386 00387 static GtsTriangle * heap_top (const heap_t * heap) 00388 { 00389 GtsTriangle * t; 00390 00391 g_assert (heap); 00392 g_assert (heap->heap); 00393 t = gts_eheap_top (heap->heap, NULL); 00394 return t; 00395 } 00396 00397 static void decrease_key (gpointer key, gpointer value, gpointer user_data) 00398 { 00399 GtsTriangle * t = key; 00400 tri_data_t * td = value; 00401 heap_t *heap = user_data; 00402 gdouble k; 00403 00404 (void) t; 00405 g_assert (heap); 00406 g_assert (heap->map); 00407 g_assert (heap->heap); 00408 g_assert (td); 00409 g_assert (!td->used); 00410 g_assert (td->pos); 00411 00412 k = tri_data_num_unused_neighbors2 (td, heap->map); 00413 g_assert (k <= td->pos->key); 00414 #ifdef DEBUG 00415 if (k == td->pos->key) 00416 g_warning ("same key: %f\n", k); 00417 #endif /* DEBUG */ 00418 if (k != td->pos->key) { 00419 g_assert (k < td->pos->key); 00420 g_assert (k >= 0.0); 00421 gts_eheap_decrease_key (heap->heap, td->pos, k); 00422 } 00423 } 00424 00425 static void heap_remove (heap_t * heap, GtsTriangle * t) 00426 { 00427 tri_data_t * td; 00428 GHashTable * h; 00429 00430 g_assert (heap); 00431 g_assert (t); 00432 td = map_lookup (heap->map, t); 00433 g_assert (td); 00434 g_assert (!td->used); 00435 g_assert (td->pos); 00436 td->used = TRUE; 00437 gts_eheap_remove (heap->heap, td->pos); 00438 td->pos = NULL; 00439 00440 /* fprintf(stderr, "td: %p\n", td); */ 00441 h = tri_data_unused_neighbors2 (td, heap->map); 00442 g_hash_table_foreach (h, decrease_key, heap); 00443 g_hash_table_destroy (h); 00444 } 00445 00446 /* map_t functions */ 00447 00448 static gint create_map_entry (gpointer item, gpointer data) 00449 { 00450 GtsTriangle * t = item; 00451 GHashTable * ht = data; 00452 tri_data_t * td; 00453 00454 g_assert (t); 00455 g_assert (ht); 00456 td = tri_data_new (t); 00457 g_hash_table_insert (ht, t, td); 00458 return 0; 00459 } 00460 00461 static void free_map_entry (gpointer key, gpointer value, gpointer user_data) 00462 { 00463 GtsTriangle * t = key; 00464 tri_data_t * td = value; 00465 00466 (void) user_data; 00467 g_assert (t); 00468 g_assert (td); 00469 g_assert (td->t == t); 00470 tri_data_destroy (td); 00471 } 00472 00473 static map_t * map_new (GtsSurface * s) 00474 { 00475 map_t * map; 00476 00477 map = g_malloc (sizeof (map_t)); 00478 map->ht = g_hash_table_new (NULL, NULL); 00479 gts_surface_foreach_face (s, create_map_entry, map->ht); 00480 return map; 00481 } 00482 00483 static void map_destroy (map_t * map) 00484 { 00485 if (!map) 00486 return; 00487 g_hash_table_foreach (map->ht, free_map_entry, NULL); 00488 g_hash_table_destroy (map->ht); 00489 g_free (map); 00490 } 00491 00492 static tri_data_t * map_lookup (const map_t * map, GtsTriangle * t) 00493 { 00494 tri_data_t * td; 00495 00496 g_assert (map); 00497 g_assert (map->ht); 00498 g_assert (t); 00499 td = g_hash_table_lookup (map->ht, t); 00500 g_assert (td); 00501 g_assert (td->t == t); 00502 return td; 00503 } 00504 00505 /* other helper functions */ 00506 00507 static GtsTriangle * find_min_neighbor (heap_t * heap, GtsTriangle * t) 00508 { 00509 GtsTriangle * min_neighbor = NULL; 00510 gdouble min_key = G_MAXDOUBLE; 00511 tri_data_t * td; 00512 GSList * li; 00513 00514 g_assert (heap); 00515 g_assert (t); 00516 00517 td = map_lookup (heap->map, t); 00518 for (li = td->neighbors; li != NULL; li = li->next) { 00519 GtsTriangle * t2 = li->data; 00520 tri_data_t * td2 = map_lookup (heap->map, t2); 00521 gdouble k; 00522 00523 g_assert (td2); 00524 if (td2->used) 00525 continue; 00526 g_assert (td2->pos); 00527 k = td2->pos->key; 00528 if (k < min_key) { 00529 min_key = k; 00530 min_neighbor = t2; 00531 } 00532 } 00533 return min_neighbor; 00534 } 00535 00536 static GtsTriangle * find_neighbor_forward (heap_t * heap, 00537 GtsTriangle * t, 00538 GtsVertex ** v1, 00539 GtsVertex ** v2, 00540 GtsVertex ** v3, 00541 gboolean left_turn) 00542 { 00543 GtsTriangle * neighbor = NULL; 00544 tri_data_t * td; 00545 GSList * li; 00546 00547 g_assert (heap); 00548 g_assert (t); 00549 g_assert (v1 && v2 && v3); 00550 g_assert (vertices_are_unique (*v1, *v2, *v3)); 00551 00552 td = map_lookup (heap->map, t); 00553 g_assert (td); 00554 for (li = td->neighbors; li && !neighbor; li = li->next) { 00555 GtsTriangle * t2 = li->data; 00556 tri_data_t * td2 = map_lookup (heap->map, t2); 00557 GtsVertex * v4, * v5, * v6; 00558 00559 g_assert (td2); 00560 if (t2 == t || td2->used) 00561 continue; 00562 gts_triangle_vertices (t2, &v4, &v5, &v6); 00563 if (left_turn) { 00564 if (!vertices_match (*v1, *v3, NULL, &v4, &v5, &v6)) 00565 continue; 00566 } else { 00567 if (!vertices_match (*v3, *v2, NULL, &v4, &v5, &v6)) 00568 continue; 00569 } 00570 neighbor = t2; 00571 *v1 = v4; 00572 *v2 = v5; 00573 *v3 = v6; 00574 } 00575 return neighbor; 00576 } 00577 00578 static GtsTriangle * find_neighbor_backward (heap_t * heap, 00579 GtsTriangle * t, 00580 GtsVertex ** v1, 00581 GtsVertex ** v2, 00582 GtsVertex ** v3, 00583 gboolean left_turn) 00584 { 00585 GtsTriangle * neighbor = NULL; 00586 tri_data_t * td; 00587 GSList * li; 00588 00589 g_assert (heap); 00590 g_assert (t); 00591 g_assert (v1 && v2 && v3); 00592 g_assert (vertices_are_unique (*v1, *v2, *v3)); 00593 00594 td = map_lookup (heap->map, t); 00595 g_assert (td); 00596 for (li = td->neighbors; li && !neighbor; li = li->next) { 00597 GtsTriangle * t2 = li->data; 00598 tri_data_t * td2 = map_lookup (heap->map, t2); 00599 GtsVertex * v4, * v5, * v6; 00600 00601 g_assert (td2); 00602 if (t2 == t || td2->used) 00603 continue; 00604 gts_triangle_vertices (t2, &v4, &v5, &v6); 00605 if (left_turn) { 00606 if (!vertices_match (NULL, *v2, *v1, &v4, &v5, &v6)) 00607 continue; 00608 } else if (!vertices_match(*v1, NULL, *v2, &v4, &v5, &v6)) 00609 continue; 00610 neighbor = t2; 00611 *v1 = v4; 00612 *v2 = v5; 00613 *v3 = v6; 00614 } 00615 return neighbor; 00616 } 00617 00618 static GSList * grow_strip_forward (heap_t * heap, 00619 GSList * strip, 00620 GtsTriangle * t, 00621 GtsVertex * v1, 00622 GtsVertex * v2, 00623 GtsVertex * v3) 00624 { 00625 gboolean left_turn; 00626 00627 g_assert (heap); 00628 g_assert (g_slist_length(strip) == 2); 00629 g_assert (t); 00630 g_assert (v1 && v2 && v3); 00631 g_assert (vertices_are_unique (v1, v2, v3)); 00632 00633 left_turn = TRUE; 00634 while ((t = find_neighbor_forward (heap, t, &v1, &v2, &v3, 00635 left_turn)) != NULL) { 00636 heap_remove (heap, t); 00637 strip = g_slist_prepend (strip, t); 00638 left_turn = !left_turn; 00639 } 00640 return strip; 00641 } 00642 00643 static GSList * grow_strip_backward (heap_t * heap, 00644 GSList * strip, 00645 GtsTriangle * t, 00646 GtsVertex * v1, 00647 GtsVertex * v2, 00648 GtsVertex * v3) 00649 { 00650 /* we have to make sure we add an even number of triangles */ 00651 GtsTriangle * t2; 00652 00653 g_assert (heap); 00654 g_assert (g_slist_length(strip) >= 2); 00655 g_assert (t); 00656 g_assert (v1 && v2 && v3); 00657 g_assert (vertices_are_unique (v1, v2, v3)); 00658 00659 while ((t2 = find_neighbor_backward (heap, t, &v1, &v2, &v3, 00660 FALSE)) != NULL 00661 && (t = find_neighbor_backward (heap, t2, &v1, &v2, &v3, 00662 TRUE)) != NULL) { 00663 heap_remove (heap, t2); 00664 heap_remove (heap, t); 00665 strip = g_slist_prepend (strip, t2); 00666 strip = g_slist_prepend (strip, t); 00667 } 00668 return strip; 00669 } 00670 00671 static gboolean find_right_turn (GtsVertex ** v1, 00672 GtsVertex ** v2, 00673 GtsVertex ** v3, 00674 GtsVertex ** v4, 00675 GtsVertex ** v5, 00676 GtsVertex ** v6) 00677 { 00678 GtsVertex * v; 00679 00680 g_assert (v1 && v2 && v3); 00681 g_assert (v4 && v5 && v6); 00682 g_assert (vertices_are_unique (*v1, *v2, *v3)); 00683 g_assert (vertices_are_unique (*v4, *v5, *v6)); 00684 g_assert (num_shared_vertices (*v1, *v2, *v3, *v4, *v5, *v6) == 2); 00685 00686 v = non_shared_vertex1 (*v1, *v2, *v3, *v4, *v5, *v6); 00687 match_vertex (v, v1, v2, v3); 00688 match_vertex (*v3, v4, v5, v6); 00689 00690 g_assert (v1 && v2 && v3); 00691 g_assert (v4 && v5 && v6); 00692 g_assert (*v4 == *v3); 00693 00694 if (*v5 == *v2) { 00695 g_assert (vertices_are_unique (*v1, *v2, *v3)); 00696 g_assert (vertices_are_unique (*v4, *v5, *v6)); 00697 g_assert (num_shared_vertices (*v1, *v2, *v3, 00698 *v4, *v5, *v6) == 2); 00699 return TRUE; 00700 } else { 00701 #ifdef DEBUG 00702 g_warning ("couldn't find a right turn"); 00703 #endif /* DEBUG */ 00704 return FALSE; 00705 } 00706 } 00707 00718 GSList * gts_surface_strip (GtsSurface *s) 00719 { 00720 GSList * strips = NULL; 00721 heap_t * heap; 00722 00723 g_return_val_if_fail (s != NULL, NULL); 00724 00725 heap = heap_new (s); 00726 while (!heap_is_empty (heap)) { 00727 GtsTriangle * t1, * t2; 00728 GtsVertex * v1, * v2, * v3, * v4, * v5, * v6; 00729 GSList * strip = NULL; 00730 00731 /* remove heap top */ 00732 t1 = heap_top (heap); 00733 g_assert (t1); 00734 heap_remove (heap, t1); 00735 00736 /* start a new strip */ 00737 strip = g_slist_prepend (strip, t1); 00738 00739 /* find second triangle */ 00740 t2 = find_min_neighbor (heap, t1); 00741 if (t2) { 00742 g_assert (t2 != t1); 00743 00744 /* find right turn */ 00745 gts_triangle_vertices (t1, &v1, &v2, &v3); 00746 gts_triangle_vertices (t2, &v4, &v5, &v6); 00747 if (find_right_turn (&v1, &v2, &v3, &v4, &v5, &v6)) { 00748 heap_remove (heap, t2); 00749 strip = g_slist_prepend (strip, t2); 00750 00751 /* grow strip forward */ 00752 strip = grow_strip_forward (heap, strip, t2, v4, v5, v6); 00753 00754 strip = g_slist_reverse (strip); 00755 00756 /* grow strip backward */ 00757 strip = grow_strip_backward (heap, strip, t1, v1, v2, v3); 00758 } 00759 } 00760 strips = g_slist_prepend (strips, strip); 00761 } 00762 strips = g_slist_reverse (strips); 00763 heap_destroy (heap); 00764 00765 return strips; 00766 }