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 <math.h> 00022 #include <string.h> 00023 #include "gts.h" 00024 00025 #include "gts-private.h" 00026 00027 static void destroy_foreach_face (GtsFace * f, GtsSurface * s) 00028 { 00029 f->surfaces = g_slist_remove (f->surfaces, s); 00030 if (!GTS_OBJECT_DESTROYED (f) && 00031 !gts_allow_floating_faces && f->surfaces == NULL) 00032 gts_object_destroy (GTS_OBJECT (f)); 00033 } 00034 00035 static void surface_destroy (GtsObject * object) 00036 { 00037 GtsSurface * surface = GTS_SURFACE (object); 00038 00039 gts_surface_foreach_face (surface, (GtsFunc) destroy_foreach_face, surface); 00040 #ifdef USE_SURFACE_BTREE 00041 g_tree_destroy (surface->faces); 00042 #else /* not USE_SURFACE_BTREE */ 00043 g_hash_table_destroy (surface->faces); 00044 #endif /* not USE_SURFACE_BTREE */ 00045 00046 (* GTS_OBJECT_CLASS (gts_surface_class ())->parent_class->destroy) (object); 00047 } 00048 00049 static void surface_write (GtsObject * object, FILE * fptr) 00050 { 00051 fprintf (fptr, " %s %s %s %s", 00052 object->klass->info.name, 00053 GTS_OBJECT_CLASS (GTS_SURFACE (object)->face_class)->info.name, 00054 GTS_OBJECT_CLASS (GTS_SURFACE (object)->edge_class)->info.name, 00055 GTS_POINT_CLASS (GTS_SURFACE (object)->vertex_class)->binary ? 00056 "GtsVertexBinary" : 00057 GTS_OBJECT_CLASS (GTS_SURFACE (object)->vertex_class)->info.name); 00058 } 00059 00060 static void surface_class_init (GtsSurfaceClass * klass) 00061 { 00062 GTS_OBJECT_CLASS (klass)->destroy = surface_destroy; 00063 GTS_OBJECT_CLASS (klass)->write = surface_write; 00064 klass->add_face = NULL; 00065 klass->remove_face = NULL; 00066 } 00067 00068 #ifdef USE_SURFACE_BTREE 00069 static gint compare_pointers (gconstpointer a, gconstpointer b) 00070 { 00071 if (GPOINTER_TO_UINT (a) < GPOINTER_TO_UINT (b)) 00072 return -1; 00073 if (GPOINTER_TO_UINT (a) > GPOINTER_TO_UINT (b)) 00074 return 1; 00075 return 0; 00076 } 00077 #endif /* USE_SURFACE_BTREE */ 00078 00079 static void surface_init (GtsSurface * surface) 00080 { 00081 #ifdef USE_SURFACE_BTREE 00082 surface->faces = g_tree_new (compare_pointers); 00083 #else /* not USE_SURFACE_BTREE */ 00084 surface->faces = g_hash_table_new (NULL, NULL); 00085 #endif /* not USE_SURFACE_BTREE */ 00086 surface->vertex_class = gts_vertex_class (); 00087 surface->edge_class = gts_edge_class (); 00088 surface->face_class = gts_face_class (); 00089 surface->keep_faces = FALSE; 00090 } 00091 00097 GtsSurfaceClass * gts_surface_class (void) 00098 { 00099 static GtsSurfaceClass * klass = NULL; 00100 00101 if (klass == NULL) { 00102 GtsObjectClassInfo surface_info = { 00103 "GtsSurface", 00104 sizeof (GtsSurface), 00105 sizeof (GtsSurfaceClass), 00106 (GtsObjectClassInitFunc) surface_class_init, 00107 (GtsObjectInitFunc) surface_init, 00108 (GtsArgSetFunc) NULL, 00109 (GtsArgGetFunc) NULL 00110 }; 00111 klass = gts_object_class_new (gts_object_class (), &surface_info); 00112 } 00113 00114 return klass; 00115 } 00116 00126 GtsSurface * gts_surface_new (GtsSurfaceClass * klass, 00127 GtsFaceClass * face_class, 00128 GtsEdgeClass * edge_class, 00129 GtsVertexClass * vertex_class) 00130 { 00131 GtsSurface * s; 00132 00133 s = GTS_SURFACE (gts_object_new (GTS_OBJECT_CLASS (klass))); 00134 s->vertex_class = vertex_class; 00135 s->edge_class = edge_class; 00136 s->face_class = face_class; 00137 00138 return s; 00139 } 00140 00148 void gts_surface_add_face (GtsSurface * s, GtsFace * f) 00149 { 00150 g_return_if_fail (s != NULL); 00151 g_return_if_fail (f != NULL); 00152 00153 g_assert (s->keep_faces == FALSE); 00154 00155 #ifdef USE_SURFACE_BTREE 00156 if (!g_tree_lookup (s->faces, f)) { 00157 f->surfaces = g_slist_prepend (f->surfaces, s); 00158 g_tree_insert (s->faces, f, f); 00159 } 00160 #else /* not USE_SURFACE_BTREE */ 00161 if (!g_hash_table_lookup (s->faces, f)) { 00162 f->surfaces = g_slist_prepend (f->surfaces, s); 00163 g_hash_table_insert (s->faces, f, f); 00164 } 00165 #endif /* not USE_SURFACE_BTREE */ 00166 00167 if (GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->add_face) 00168 (* GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->add_face) (s, f); 00169 } 00170 00178 void gts_surface_remove_face (GtsSurface * s, 00179 GtsFace * f) 00180 { 00181 g_return_if_fail (s != NULL); 00182 g_return_if_fail (f != NULL); 00183 00184 g_assert (s->keep_faces == FALSE); 00185 00186 #ifdef USE_SURFACE_BTREE 00187 g_tree_remove (s->faces, f); 00188 #else /* not USE_SURFACE_BTREE */ 00189 g_hash_table_remove (s->faces, f); 00190 #endif /* not USE_SURFACE_BTREE */ 00191 00192 f->surfaces = g_slist_remove (f->surfaces, s); 00193 00194 if (GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->remove_face) 00195 (* GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->remove_face) (s, f); 00196 00197 if (!GTS_OBJECT_DESTROYED (f) && 00198 !gts_allow_floating_faces && 00199 f->surfaces == NULL) 00200 gts_object_destroy (GTS_OBJECT (f)); 00201 } 00202 00215 /* Update split.c/surface_read() if modifying this function */ 00216 guint gts_surface_read (GtsSurface * surface, GtsFile * f) 00217 { 00218 GtsVertex ** vertices; 00219 GtsEdge ** edges; 00220 guint n, nv, ne, nf; 00221 00222 g_return_val_if_fail (surface != NULL, 1); 00223 g_return_val_if_fail (f != NULL, 1); 00224 00225 if (f->type != GTS_INT) { 00226 gts_file_error (f, "expecting an integer (number of vertices)"); 00227 return f->line; 00228 } 00229 nv = atoi (f->token->str); 00230 00231 gts_file_next_token (f); 00232 if (f->type != GTS_INT) { 00233 gts_file_error (f, "expecting an integer (number of edges)"); 00234 return f->line; 00235 } 00236 ne = atoi (f->token->str); 00237 00238 gts_file_next_token (f); 00239 if (f->type != GTS_INT) { 00240 gts_file_error (f, "expecting an integer (number of faces)"); 00241 return f->line; 00242 } 00243 nf = atoi (f->token->str); 00244 00245 gts_file_next_token (f); 00246 if (f->type == GTS_STRING) { 00247 if (f->type != GTS_STRING) { 00248 gts_file_error (f, "expecting a string (GtsSurfaceClass)"); 00249 return f->line; 00250 } 00251 gts_file_next_token (f); 00252 if (f->type != GTS_STRING) { 00253 gts_file_error (f, "expecting a string (GtsFaceClass)"); 00254 return f->line; 00255 } 00256 gts_file_next_token (f); 00257 if (f->type != GTS_STRING) { 00258 gts_file_error (f, "expecting a string (GtsEdgeClass)"); 00259 return f->line; 00260 } 00261 gts_file_next_token (f); 00262 if (f->type != GTS_STRING) { 00263 gts_file_error (f, "expecting a string (GtsVertexClass)"); 00264 return f->line; 00265 } 00266 if (!strcmp (f->token->str, "GtsVertexBinary")) 00267 GTS_POINT_CLASS (surface->vertex_class)->binary = TRUE; 00268 else { 00269 GTS_POINT_CLASS (surface->vertex_class)->binary = FALSE; 00270 gts_file_first_token_after (f, '\n'); 00271 } 00272 } 00273 else 00274 gts_file_first_token_after (f, '\n'); 00275 00276 if (nf <= 0) 00277 return 0; 00278 00279 /* allocate nv + 1 just in case nv == 0 */ 00280 vertices = g_malloc ((nv + 1)*sizeof (GtsVertex *)); 00281 edges = g_malloc ((ne + 1)*sizeof (GtsEdge *)); 00282 00283 n = 0; 00284 while (n < nv && f->type != GTS_ERROR) { 00285 GtsObject * new_vertex = 00286 gts_object_new (GTS_OBJECT_CLASS (surface->vertex_class)); 00287 00288 (* GTS_OBJECT_CLASS (surface->vertex_class)->read) (&new_vertex, f); 00289 if (f->type != GTS_ERROR) { 00290 if (!GTS_POINT_CLASS (surface->vertex_class)->binary) 00291 gts_file_first_token_after (f, '\n'); 00292 vertices[n++] = GTS_VERTEX (new_vertex); 00293 } 00294 else 00295 gts_object_destroy (new_vertex); 00296 } 00297 if (f->type == GTS_ERROR) 00298 nv = n; 00299 if (GTS_POINT_CLASS (surface->vertex_class)->binary) 00300 gts_file_first_token_after (f, '\n'); 00301 00302 n = 0; 00303 while (n < ne && f->type != GTS_ERROR) { 00304 guint p1, p2; 00305 00306 if (f->type != GTS_INT) 00307 gts_file_error (f, "expecting an integer (first vertex index)"); 00308 else { 00309 p1 = atoi (f->token->str); 00310 if (p1 == 0 || p1 > nv) 00311 gts_file_error (f, "vertex index `%d' is out of range `[1,%d]'", 00312 p1, nv); 00313 else { 00314 gts_file_next_token (f); 00315 if (f->type != GTS_INT) 00316 gts_file_error (f, "expecting an integer (second vertex index)"); 00317 else { 00318 p2 = atoi (f->token->str); 00319 if (p2 == 0 || p2 > nv) 00320 gts_file_error (f, "vertex index `%d' is out of range `[1,%d]'", 00321 p2, nv); 00322 else { 00323 GtsEdge * new_edge = 00324 gts_edge_new (surface->edge_class, 00325 vertices[p1 - 1], vertices[p2 - 1]); 00326 00327 gts_file_next_token (f); 00328 if (f->type != '\n') 00329 if (GTS_OBJECT_CLASS (surface->edge_class)->read) 00330 (*GTS_OBJECT_CLASS (surface->edge_class)->read) 00331 ((GtsObject **) &new_edge, f); 00332 gts_file_first_token_after (f, '\n'); 00333 edges[n++] = new_edge; 00334 } 00335 } 00336 } 00337 } 00338 } 00339 if (f->type == GTS_ERROR) 00340 ne = n; 00341 00342 n = 0; 00343 while (n < nf && f->type != GTS_ERROR) { 00344 guint s1, s2, s3; 00345 00346 if (f->type != GTS_INT) 00347 gts_file_error (f, "expecting an integer (first edge index)"); 00348 else { 00349 s1 = atoi (f->token->str); 00350 if (s1 == 0 || s1 > ne) 00351 gts_file_error (f, "edge index `%d' is out of range `[1,%d]'", 00352 s1, ne); 00353 else { 00354 gts_file_next_token (f); 00355 if (f->type != GTS_INT) 00356 gts_file_error (f, "expecting an integer (second edge index)"); 00357 else { 00358 s2 = atoi (f->token->str); 00359 if (s2 == 0 || s2 > ne) 00360 gts_file_error (f, "edge index `%d' is out of range `[1,%d]'", 00361 s2, ne); 00362 else { 00363 gts_file_next_token (f); 00364 if (f->type != GTS_INT) 00365 gts_file_error (f, "expecting an integer (third edge index)"); 00366 else { 00367 s3 = atoi (f->token->str); 00368 if (s3 == 0 || s3 > ne) 00369 gts_file_error (f, "edge index `%d' is out of range `[1,%d]'", 00370 s3, ne); 00371 else { 00372 GtsFace * new_face = gts_face_new (surface->face_class, 00373 edges[s1 - 1], 00374 edges[s2 - 1], 00375 edges[s3 - 1]); 00376 00377 gts_file_next_token (f); 00378 if (f->type != '\n') 00379 if (GTS_OBJECT_CLASS (surface->face_class)->read) 00380 (*GTS_OBJECT_CLASS (surface->face_class)->read) 00381 ((GtsObject **) &new_face, f); 00382 gts_file_first_token_after (f, '\n'); 00383 gts_surface_add_face (surface, new_face); 00384 n++; 00385 } 00386 } 00387 } 00388 } 00389 } 00390 } 00391 } 00392 00393 if (f->type == GTS_ERROR) { 00394 gts_allow_floating_vertices = TRUE; 00395 while (nv) 00396 gts_object_destroy (GTS_OBJECT (vertices[nv-- - 1])); 00397 gts_allow_floating_vertices = FALSE; 00398 } 00399 00400 g_free (vertices); 00401 g_free (edges); 00402 00403 if (f->type == GTS_ERROR) 00404 return f->line; 00405 return 0; 00406 } 00407 00408 static void sum_area (GtsFace * f, gdouble * area) { 00409 *area += gts_triangle_area (GTS_TRIANGLE (f)); 00410 } 00411 00419 gdouble gts_surface_area (GtsSurface * s) 00420 { 00421 gdouble area = 0.0; 00422 gts_surface_foreach_face (s, (GtsFunc)sum_area, &area); 00423 return area; 00424 } 00425 00432 void gts_range_init (GtsRange * r) 00433 { 00434 g_return_if_fail (r != NULL); 00435 00436 r->max = - G_MAXDOUBLE; 00437 r->min = G_MAXDOUBLE; 00438 r->sum = r->sum2 = 0.0; 00439 r->n = 0; 00440 } 00441 00448 void gts_range_reset (GtsRange * r) 00449 { 00450 g_return_if_fail (r != NULL); 00451 00452 r->max = 0.0; 00453 r->min = 0.0; 00454 r->sum = r->sum2 = 0.0; 00455 r->n = 0; 00456 } 00457 00465 void gts_range_add_value (GtsRange * r, gdouble val) 00466 { 00467 g_return_if_fail (r != NULL); 00468 00469 if (val < r->min) r->min = val; 00470 if (val > r->max) r->max = val; 00471 r->sum += val; 00472 r->sum2 += val*val; 00473 r->n++; 00474 } 00475 00482 void gts_range_update (GtsRange * r) 00483 { 00484 g_return_if_fail (r != NULL); 00485 00486 if (r->n > 0) { 00487 if (r->sum2 - r->sum*r->sum/(gdouble) r->n >= 0.) 00488 r->stddev = sqrt ((r->sum2 - r->sum*r->sum/(gdouble) r->n) 00489 /(gdouble) r->n); 00490 else 00491 r->stddev = 0.; 00492 r->mean = r->sum/(gdouble) r->n; 00493 } 00494 else 00495 r->min = r->max = r->mean = r->stddev = 0.; 00496 } 00497 00505 void gts_range_print (GtsRange * r, FILE * fptr) 00506 { 00507 g_return_if_fail (r != NULL); 00508 g_return_if_fail (fptr != NULL); 00509 fprintf (fptr, "min: %g mean: %g | %g max: %g", 00510 r->min, r->mean, r->stddev, r->max); 00511 } 00512 00513 static void stats_foreach_vertex (GtsVertex * v, GtsSurfaceStats * stats) 00514 { 00515 GSList * i = v->segments; 00516 guint nedges = 0; 00517 00518 while (i) { 00519 if (GTS_IS_EDGE (i->data) && 00520 gts_edge_has_parent_surface (i->data, stats->parent)) 00521 nedges++; 00522 i = i->next; 00523 } 00524 gts_range_add_value (&stats->edges_per_vertex, nedges); 00525 } 00526 00527 static void stats_foreach_edge (GtsEdge * e, GtsSurfaceStats * stats) 00528 { 00529 guint nt = gts_edge_face_number (e, stats->parent); 00530 00531 if (gts_segment_is_duplicate (GTS_SEGMENT (e))) 00532 stats->n_duplicate_edges++; 00533 if (nt == 1) 00534 stats->n_boundary_edges++; 00535 else if (nt > 2) 00536 stats->n_non_manifold_edges++; 00537 gts_range_add_value (&stats->faces_per_edge, nt); 00538 } 00539 00540 static void stats_foreach_face (GtsTriangle * t, GtsSurfaceStats * stats) 00541 { 00542 if (!gts_face_is_compatible (GTS_FACE (t), stats->parent)) 00543 stats->n_incompatible_faces++; 00544 if (gts_triangle_is_duplicate (t)) 00545 stats->n_duplicate_faces++; 00546 stats->n_faces++; 00547 } 00548 00556 void gts_surface_stats (GtsSurface * s, GtsSurfaceStats * stats) 00557 { 00558 g_return_if_fail (s != NULL); 00559 g_return_if_fail (stats != NULL); 00560 00561 stats->parent = s; 00562 stats->n_faces = 0; 00563 stats->n_incompatible_faces = 0; 00564 stats->n_duplicate_faces = 0; 00565 stats->n_duplicate_edges = 0; 00566 stats->n_boundary_edges = 0; 00567 stats->n_non_manifold_edges = 0; 00568 gts_range_init (&stats->edges_per_vertex); 00569 gts_range_init (&stats->faces_per_edge); 00570 00571 gts_surface_foreach_vertex (s, (GtsFunc) stats_foreach_vertex, stats); 00572 gts_surface_foreach_edge (s, (GtsFunc) stats_foreach_edge, stats); 00573 gts_surface_foreach_face (s, (GtsFunc) stats_foreach_face, stats); 00574 00575 gts_range_update (&stats->edges_per_vertex); 00576 gts_range_update (&stats->faces_per_edge); 00577 } 00578 00579 static void quality_foreach_edge (GtsSegment * s, 00580 GtsSurfaceQualityStats * stats) 00581 { 00582 GSList * i = GTS_EDGE (s)->triangles; 00583 00584 gts_range_add_value (&stats->edge_length, 00585 gts_point_distance (GTS_POINT (s->v1), 00586 GTS_POINT (s->v2))); 00587 while (i) { 00588 GSList * j = i->next; 00589 while (j) { 00590 gts_range_add_value (&stats->edge_angle, 00591 fabs (gts_triangles_angle (i->data, j->data))); 00592 j = j->next; 00593 } 00594 i = i->next; 00595 } 00596 } 00597 00598 static void quality_foreach_face (GtsTriangle * t, 00599 GtsSurfaceQualityStats * stats) 00600 { 00601 gts_range_add_value (&stats->face_quality, gts_triangle_quality (t)); 00602 gts_range_add_value (&stats->face_area, gts_triangle_area (t)); 00603 } 00604 00612 void gts_surface_quality_stats (GtsSurface * s, GtsSurfaceQualityStats * stats) 00613 { 00614 g_return_if_fail (s != NULL); 00615 g_return_if_fail (stats != NULL); 00616 00617 stats->parent = s; 00618 gts_range_init (&stats->face_quality); 00619 gts_range_init (&stats->face_area); 00620 gts_range_init (&stats->edge_length); 00621 gts_range_init (&stats->edge_angle); 00622 00623 gts_surface_foreach_edge (s, (GtsFunc) quality_foreach_edge, stats); 00624 gts_surface_foreach_face (s, (GtsFunc) quality_foreach_face, stats); 00625 00626 gts_range_update (&stats->face_quality); 00627 gts_range_update (&stats->face_area); 00628 gts_range_update (&stats->edge_length); 00629 gts_range_update (&stats->edge_angle); 00630 } 00631 00639 void gts_surface_print_stats (GtsSurface * s, FILE * fptr) 00640 { 00641 GtsSurfaceStats stats; 00642 GtsSurfaceQualityStats qstats; 00643 00644 g_return_if_fail (s != NULL); 00645 g_return_if_fail (fptr != NULL); 00646 00647 gts_surface_stats (s, &stats); 00648 gts_surface_quality_stats (s, &qstats); 00649 00650 fprintf (fptr, 00651 "# vertices: %u edges: %u faces: %u\n" 00652 "# Connectivity statistics\n" 00653 "# incompatible faces: %u\n" 00654 "# duplicate faces: %u\n" 00655 "# boundary edges: %u\n" 00656 "# duplicate edges: %u\n" 00657 "# non-manifold edges: %u\n", 00658 stats.edges_per_vertex.n, 00659 stats.faces_per_edge.n, 00660 stats.n_faces, 00661 stats.n_incompatible_faces, 00662 stats.n_duplicate_faces, 00663 stats.n_boundary_edges, 00664 stats.n_duplicate_edges, 00665 stats.n_non_manifold_edges); 00666 fputs ("# edges per vertex: ", fptr); 00667 gts_range_print (&stats.edges_per_vertex, fptr); 00668 fputs ("\n# faces per edge: ", fptr); 00669 gts_range_print (&stats.faces_per_edge, fptr); 00670 fputs ("\n# Geometric statistics\n# face quality: ", fptr); 00671 gts_range_print (&qstats.face_quality, fptr); 00672 fputs ("\n# face area : ", fptr); 00673 gts_range_print (&qstats.face_area, fptr); 00674 fputs ("\n# edge length : ", fptr); 00675 gts_range_print (&qstats.edge_length, fptr); 00676 fputc ('\n', fptr); 00677 } 00678 00679 static void write_vertex (GtsPoint * p, gpointer * data) 00680 { 00681 (*GTS_OBJECT (p)->klass->write) (GTS_OBJECT (p), (FILE *) data[0]); 00682 if (!GTS_POINT_CLASS (GTS_OBJECT (p)->klass)->binary) 00683 fputc ('\n', (FILE *) data[0]); 00684 g_hash_table_insert (data[2], p, 00685 GUINT_TO_POINTER (++(*((guint *) data[1])))); 00686 } 00687 00688 static void write_edge (GtsSegment * s, gpointer * data) 00689 { 00690 fprintf ((FILE *) data[0], "%u %u", 00691 GPOINTER_TO_UINT (g_hash_table_lookup (data[2], s->v1)), 00692 GPOINTER_TO_UINT (g_hash_table_lookup (data[2], s->v2))); 00693 if (GTS_OBJECT (s)->klass->write) 00694 (*GTS_OBJECT (s)->klass->write) (GTS_OBJECT (s), (FILE *) data[0]); 00695 fputc ('\n', (FILE *) data[0]); 00696 g_hash_table_insert (data[3], s, 00697 GUINT_TO_POINTER (++(*((guint *) data[1])))); 00698 } 00699 00700 static void write_face (GtsTriangle * t, gpointer * data) 00701 { 00702 fprintf (data[0], "%u %u %u", 00703 GPOINTER_TO_UINT (g_hash_table_lookup (data[3], t->e1)), 00704 GPOINTER_TO_UINT (g_hash_table_lookup (data[3], t->e2)), 00705 GPOINTER_TO_UINT (g_hash_table_lookup (data[3], t->e3))); 00706 if (GTS_OBJECT (t)->klass->write) 00707 (*GTS_OBJECT (t)->klass->write) (GTS_OBJECT (t), data[0]); 00708 fputc ('\n', data[0]); 00709 } 00710 00738 void gts_surface_write (GtsSurface * s, FILE * fptr) 00739 { 00740 guint n; 00741 gpointer data[4]; 00742 GHashTable * vindex, * eindex; 00743 GtsSurfaceStats stats; 00744 00745 g_return_if_fail (s != NULL); 00746 g_return_if_fail (fptr != NULL); 00747 00748 data[0] = fptr; 00749 data[1] = &n; 00750 data[2] = vindex = g_hash_table_new (NULL, NULL); 00751 data[3] = eindex = g_hash_table_new (NULL, NULL); 00752 00753 gts_surface_stats (s, &stats); 00754 fprintf (fptr, "%u %u %u", 00755 stats.edges_per_vertex.n, 00756 stats.faces_per_edge.n, 00757 stats.n_faces); 00758 if (GTS_OBJECT (s)->klass->write) 00759 (*GTS_OBJECT (s)->klass->write) (GTS_OBJECT (s), fptr); 00760 fputc ('\n', fptr); 00761 n = 0; 00762 gts_surface_foreach_vertex (s, (GtsFunc) write_vertex, data); 00763 n = 0; 00764 if (GTS_POINT_CLASS (s->vertex_class)->binary) 00765 fputc ('\n', fptr); 00766 gts_surface_foreach_edge (s, (GtsFunc) write_edge, data); 00767 gts_surface_foreach_face (s, (GtsFunc) write_face, data); 00768 g_hash_table_destroy (vindex); 00769 g_hash_table_destroy (eindex); 00770 } 00771 00772 static void write_vertex_oogl (GtsPoint * p, gpointer * data) 00773 { 00774 FILE * fp = data[0]; 00775 00776 fprintf (fp, "%g %g %g", p->x, p->y, p->z); 00777 if (GTS_OBJECT (p)->klass->color) { 00778 GtsColor c = (* GTS_OBJECT (p)->klass->color) (GTS_OBJECT (p)); 00779 fprintf (fp, " %g %g %g 1.0\n", c.r, c.g, c.b); 00780 } 00781 else 00782 fputc ('\n', fp); 00783 GTS_OBJECT (p)->reserved = GUINT_TO_POINTER ((*((guint *) data[1]))++); 00784 } 00785 00786 static void write_face_oogl (GtsTriangle * t, FILE * fp) 00787 { 00788 GtsVertex * v1, * v2, * v3; 00789 gts_triangle_vertices (t, &v1, &v2, &v3); 00790 fprintf (fp, "3 %u %u %u", 00791 GPOINTER_TO_UINT (GTS_OBJECT (v1)->reserved), 00792 GPOINTER_TO_UINT (GTS_OBJECT (v2)->reserved), 00793 GPOINTER_TO_UINT (GTS_OBJECT (v3)->reserved)); 00794 if (GTS_OBJECT (t)->klass->color) { 00795 GtsColor c = (* GTS_OBJECT (t)->klass->color) (GTS_OBJECT (t)); 00796 fprintf (fp, " %g %g %g\n", c.r, c.g, c.b); 00797 } 00798 else 00799 fputc ('\n', fp); 00800 } 00801 00809 void gts_surface_write_oogl (GtsSurface * s, FILE * fptr) 00810 { 00811 guint n = 0; 00812 gpointer data[2]; 00813 GtsSurfaceStats stats; 00814 00815 g_return_if_fail (s != NULL); 00816 g_return_if_fail (fptr != NULL); 00817 00818 data[0] = fptr; 00819 data[1] = &n; 00820 00821 gts_surface_stats (s, &stats); 00822 if (GTS_OBJECT_CLASS (s->vertex_class)->color) 00823 fputs ("COFF ", fptr); 00824 else 00825 fputs ("OFF ", fptr); 00826 fprintf (fptr, "%u %u %u\n", 00827 stats.edges_per_vertex.n, 00828 stats.n_faces, 00829 stats.faces_per_edge.n); 00830 gts_surface_foreach_vertex (s, (GtsFunc) write_vertex_oogl, data); 00831 gts_surface_foreach_face (s, (GtsFunc) write_face_oogl, fptr); 00832 gts_surface_foreach_vertex (s, (GtsFunc) gts_object_reset_reserved, NULL); 00833 } 00834 00835 static void write_vertex_vtk (GtsPoint * p, gpointer * data) 00836 { 00837 FILE * fp = data[0]; 00838 00839 fprintf (fp, "%g %g %g\n", p->x, p->y, p->z); 00840 GTS_OBJECT (p)->reserved = GUINT_TO_POINTER ((*((guint *) data[1]))++); 00841 } 00842 00843 static void write_face_vtk (GtsTriangle * t, FILE * fp) 00844 { 00845 GtsVertex * v1, * v2, * v3; 00846 gts_triangle_vertices (t, &v1, &v2, &v3); 00847 fprintf (fp, "3 %u %u %u\n", 00848 GPOINTER_TO_UINT (GTS_OBJECT (v1)->reserved), 00849 GPOINTER_TO_UINT (GTS_OBJECT (v2)->reserved), 00850 GPOINTER_TO_UINT (GTS_OBJECT (v3)->reserved)); 00851 } 00852 00860 void gts_surface_write_vtk (GtsSurface * s, FILE * fptr) 00861 { 00862 guint n = 0; 00863 gpointer data[2]; 00864 GtsSurfaceStats stats; 00865 00866 g_return_if_fail (s != NULL); 00867 g_return_if_fail (fptr != NULL); 00868 00869 data[0] = fptr; 00870 data[1] = &n; 00871 00872 gts_surface_stats (s, &stats); 00873 fprintf (fptr, 00874 "# vtk DataFile Version 2.0\n" 00875 "Generated by GTS\n" 00876 "ASCII\n" 00877 "DATASET POLYDATA\n" 00878 "POINTS %u float\n", 00879 stats.edges_per_vertex.n); 00880 gts_surface_foreach_vertex (s, (GtsFunc) write_vertex_vtk, data); 00881 fprintf (fptr, 00882 "POLYGONS %u %u\n", 00883 stats.n_faces, stats.n_faces*4); 00884 gts_surface_foreach_face (s, (GtsFunc) write_face_vtk, fptr); 00885 gts_surface_foreach_vertex (s, (GtsFunc) gts_object_reset_reserved, NULL); 00886 } 00887 00888 static void write_edge_oogl_boundary (GtsSegment * s, gpointer * data) 00889 { 00890 if (!gts_edge_is_boundary (GTS_EDGE (s), data[1])) 00891 return; 00892 00893 if (GTS_OBJECT (s)->klass->color) { 00894 GtsColor c = (* GTS_OBJECT (s)->klass->color) (GTS_OBJECT (s)); 00895 fprintf (data[0], "VECT 1 2 1 2 1 %g %g %g %g %g %g %g %g %g 1.\n", 00896 GTS_POINT (s->v1)->x, GTS_POINT (s->v1)->y, GTS_POINT (s->v1)->z, 00897 GTS_POINT (s->v2)->x, GTS_POINT (s->v2)->y, GTS_POINT (s->v2)->z, 00898 c.r, c.g, c.b); 00899 } 00900 else 00901 fprintf (data[0], "VECT 1 2 0 2 0 %g %g %g %g %g %g\n", 00902 GTS_POINT (s->v1)->x, GTS_POINT (s->v1)->y, GTS_POINT (s->v1)->z, 00903 GTS_POINT (s->v2)->x, GTS_POINT (s->v2)->y, GTS_POINT (s->v2)->z); 00904 } 00905 00914 void gts_surface_write_oogl_boundary (GtsSurface * s, FILE * fptr) 00915 { 00916 gpointer data[2]; 00917 00918 g_return_if_fail (s != NULL); 00919 g_return_if_fail (fptr != NULL); 00920 00921 data[0] = fptr; 00922 data[1] = s; 00923 fputs ("LIST {\n", fptr); 00924 gts_surface_foreach_edge (s, (GtsFunc) write_edge_oogl_boundary, data); 00925 fputs ("}\n", fptr); 00926 } 00927 00928 #ifdef USE_SURFACE_BTREE 00929 static gint vertex_foreach_face (GtsTriangle * t, 00930 gpointer t_data, 00931 gpointer * info) 00932 #else /* not USE_SURFACE_BTREE */ 00933 static void vertex_foreach_face (GtsTriangle * t, 00934 gpointer t_data, 00935 gpointer * info) 00936 #endif /* not USE_SURFACE_BTREE */ 00937 { 00938 GHashTable * hash = info[0]; 00939 gpointer data = info[1]; 00940 GtsFunc func = (GtsFunc) info[2]; 00941 GtsSegment 00942 * s1 = GTS_SEGMENT (t->e1); 00943 00944 if (!g_hash_table_lookup (hash, s1->v1)) { 00945 (*func) (s1->v1, data); 00946 g_hash_table_insert (hash, s1->v1, GINT_TO_POINTER (-1)); 00947 } 00948 if (!g_hash_table_lookup (hash, s1->v2)) { 00949 (*func) (s1->v2, data); 00950 g_hash_table_insert (hash, s1->v2, GINT_TO_POINTER (-1)); 00951 } 00952 if (!g_hash_table_lookup (hash, gts_triangle_vertex (t))) { 00953 (*func) (gts_triangle_vertex (t), data); 00954 g_hash_table_insert (hash, gts_triangle_vertex (t), 00955 GINT_TO_POINTER (-1)); 00956 } 00957 #ifdef USE_SURFACE_BTREE 00958 return FALSE; 00959 #endif /* USE_SURFACE_BTREE */ 00960 } 00961 00970 void gts_surface_foreach_vertex (GtsSurface * s, GtsFunc func, gpointer data) 00971 { 00972 gpointer info[3]; 00973 00974 g_return_if_fail (s != NULL); 00975 g_return_if_fail (func != NULL); 00976 00977 /* forbid removal of faces */ 00978 s->keep_faces = TRUE; 00979 info[0] = g_hash_table_new (NULL, NULL); 00980 info[1] = data; 00981 info[2] = func; 00982 #ifdef USE_SURFACE_BTREE 00983 g_tree_traverse (s->faces, (GTraverseFunc) vertex_foreach_face, G_IN_ORDER, 00984 info); 00985 #else /* not USE_SURFACE_BTREE */ 00986 g_hash_table_foreach (s->faces, (GHFunc) vertex_foreach_face, info); 00987 #endif /* not USE_SURFACE_BTREE */ 00988 g_hash_table_destroy (info[0]); 00989 /* allow removal of faces */ 00990 s->keep_faces = FALSE; 00991 } 00992 00993 #ifdef USE_SURFACE_BTREE 00994 static gint edge_foreach_face (GtsTriangle * t, 00995 gpointer t_data, 00996 gpointer * info) 00997 #else /* not USE_SURFACE_BTREE */ 00998 static void edge_foreach_face (GtsTriangle * t, 00999 gpointer t_data, 01000 gpointer * info) 01001 #endif /* not USE_SURFACE_BTREE */ 01002 { 01003 GHashTable * hash = info[0]; 01004 gpointer data = info[1]; 01005 GtsFunc func = (GtsFunc) info[2]; 01006 01007 if (!g_hash_table_lookup (hash, t->e1)) { 01008 (*func) (t->e1, data); 01009 g_hash_table_insert (hash, t->e1, GINT_TO_POINTER (-1)); 01010 } 01011 if (!g_hash_table_lookup (hash, t->e2)) { 01012 (*func) (t->e2, data); 01013 g_hash_table_insert (hash, t->e2, GINT_TO_POINTER (-1)); 01014 } 01015 if (!g_hash_table_lookup (hash, t->e3)) { 01016 (*func) (t->e3, data); 01017 g_hash_table_insert (hash, t->e3, GINT_TO_POINTER (-1)); 01018 } 01019 #ifdef USE_SURFACE_BTREE 01020 return FALSE; 01021 #endif /* not USE_SURFACE_BTREE */ 01022 } 01023 01032 void gts_surface_foreach_edge (GtsSurface * s, GtsFunc func, gpointer data) 01033 { 01034 gpointer info[3]; 01035 01036 g_return_if_fail (s != NULL); 01037 g_return_if_fail (func != NULL); 01038 01039 /* forbid removal of faces */ 01040 s->keep_faces = TRUE; 01041 info[0] = g_hash_table_new (NULL, NULL); 01042 info[1] = data; 01043 info[2] = func; 01044 #ifdef USE_SURFACE_BTREE 01045 g_tree_traverse (s->faces, (GTraverseFunc) edge_foreach_face, G_IN_ORDER, 01046 info); 01047 #else /* not USE_SURFACE_BTREE */ 01048 g_hash_table_foreach (s->faces, (GHFunc) edge_foreach_face, info); 01049 #endif /* not USE_SURFACE_BTREE */ 01050 g_hash_table_destroy (info[0]); 01051 /* allow removal of faces */ 01052 s->keep_faces = FALSE; 01053 } 01054 01055 #ifdef USE_SURFACE_BTREE 01056 static gint foreach_face (GtsFace * f, 01057 gpointer t_data, 01058 gpointer * info) 01059 #else /* not USE_SURFACE_BTREE */ 01060 static void foreach_face (GtsFace * f, 01061 gpointer t_data, 01062 gpointer * info) 01063 #endif /* not USE_SURFACE_BTREE */ 01064 { 01065 (*((GtsFunc) info[0])) (f, info[1]); 01066 #ifdef USE_SURFACE_BTREE 01067 return FALSE; 01068 #endif /* USE_SURFACE_BTREE */ 01069 } 01070 01079 void gts_surface_foreach_face (GtsSurface * s, 01080 GtsFunc func, 01081 gpointer data) 01082 { 01083 gpointer info[2]; 01084 01085 g_return_if_fail (s != NULL); 01086 g_return_if_fail (func != NULL); 01087 01088 /* forbid removal of faces */ 01089 s->keep_faces = TRUE; 01090 info[0] = func; 01091 info[1] = data; 01092 #ifdef USE_SURFACE_BTREE 01093 g_tree_traverse (s->faces, (GTraverseFunc) foreach_face, G_IN_ORDER, 01094 info); 01095 #else /* not USE_SURFACE_BTREE */ 01096 g_hash_table_foreach (s->faces, (GHFunc) foreach_face, info); 01097 #endif /* not USE_SURFACE_BTREE */ 01098 /* allow removal of faces */ 01099 s->keep_faces = FALSE; 01100 } 01101 01102 #ifdef USE_SURFACE_BTREE 01103 static gint foreach_face_remove (GtsFace * f, 01104 gpointer t_data, 01105 gpointer * info) 01106 { 01107 if ((*((GtsFunc) info[0])) (f, info[1])) { 01108 GtsSurface * s = info[2]; 01109 guint * n = info[3]; 01110 01111 f->surfaces = g_slist_remove (f->surfaces, s); 01112 if (!GTS_OBJECT_DESTROYED (f) && 01113 !gts_allow_floating_faces && 01114 f->surfaces == NULL) 01115 gts_object_destroy (GTS_OBJECT (f)); 01116 01117 if (GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->remove_face) 01118 (* GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->remove_face) (s, f); 01119 01120 g_tree_remove (s->faces, f); 01121 (*n)++; 01122 } 01123 return FALSE; 01124 } 01125 #else /* not USE_SURFACE_BTREE */ 01126 static gboolean foreach_face_remove (GtsFace * f, 01127 gpointer t_data, 01128 gpointer * info) 01129 { 01130 if ((*((GtsFunc) info[0])) (f, info[1])) { 01131 GtsSurface * s = info[2]; 01132 01133 f->surfaces = g_slist_remove (f->surfaces, s); 01134 if (!GTS_OBJECT_DESTROYED (f) && 01135 !gts_allow_floating_faces && 01136 f->surfaces == NULL) 01137 gts_object_destroy (GTS_OBJECT (f)); 01138 01139 if (GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->remove_face) 01140 (* GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass)->remove_face) (s, f); 01141 01142 return TRUE; 01143 } 01144 return FALSE; 01145 } 01146 #endif /* not USE_SURFACE_BTREE */ 01147 01161 guint gts_surface_foreach_face_remove (GtsSurface * s, 01162 GtsFunc func, 01163 gpointer data) 01164 { 01165 gpointer info[4]; 01166 guint n = 0; 01167 01168 g_return_val_if_fail (s != NULL, 0); 01169 g_return_val_if_fail (func != NULL, 0); 01170 01171 /* forbid removal of faces */ 01172 s->keep_faces = TRUE; 01173 info[0] = func; 01174 info[1] = data; 01175 info[2] = s; 01176 #ifdef USE_SURFACE_BTREE 01177 info[3] = &n; 01178 g_tree_traverse (s->faces, (GTraverseFunc) foreach_face_remove, G_PRE_ORDER, 01179 info); 01180 #else /* not USE_SURFACE_BTREE */ 01181 n = g_hash_table_foreach_remove (s->faces, 01182 (GHRFunc) foreach_face_remove, 01183 info); 01184 #endif /* not USE_SURFACE_BTREE */ 01185 /* allow removal of faces */ 01186 s->keep_faces = FALSE; 01187 01188 return n; 01189 } 01190 01191 static void midvertex_insertion (GtsEdge * e, 01192 GtsSurface * surface, 01193 GtsEHeap * heap, 01194 GtsRefineFunc refine_func, 01195 gpointer refine_data, 01196 GtsVertexClass * vertex_class, 01197 GtsEdgeClass * edge_class) 01198 { 01199 GtsVertex * midvertex; 01200 GtsEdge * e1, * e2; 01201 GSList * i; 01202 01203 midvertex = (*refine_func) (e, vertex_class, refine_data); 01204 e1 = gts_edge_new (edge_class, GTS_SEGMENT (e)->v1, midvertex); 01205 gts_eheap_insert (heap, e1); 01206 e2 = gts_edge_new (edge_class, GTS_SEGMENT (e)->v2, midvertex); 01207 gts_eheap_insert (heap, e2); 01208 01209 /* creates new faces and modifies old ones */ 01210 i = e->triangles; 01211 while (i) { 01212 GtsTriangle * t = i->data; 01213 GtsVertex * v1, * v2, * v3; 01214 GtsEdge * te2, * te3, * ne, * tmp; 01215 01216 gts_triangle_vertices_edges (t, e, &v1, &v2, &v3, &e, &te2, &te3); 01217 ne = gts_edge_new (edge_class, midvertex, v3); 01218 gts_eheap_insert (heap, ne); 01219 if (GTS_SEGMENT (e1)->v1 == v2) { 01220 tmp = e1; e1 = e2; e2 = tmp; 01221 } 01222 e1->triangles = g_slist_prepend (e1->triangles, t); 01223 ne->triangles = g_slist_prepend (ne->triangles, t); 01224 te2->triangles = g_slist_remove (te2->triangles, t); 01225 t->e1 = e1; t->e2 = ne; t->e3 = te3; 01226 gts_surface_add_face (surface, 01227 gts_face_new (surface->face_class, e2, te2, ne)); 01228 i = i->next; 01229 } 01230 /* destroys edge */ 01231 g_slist_free (e->triangles); 01232 e->triangles = NULL; 01233 gts_object_destroy (GTS_OBJECT (e)); 01234 } 01235 01236 static gdouble edge_length2_inverse (GtsSegment * s) 01237 { 01238 return - gts_point_distance2 (GTS_POINT (s->v1), GTS_POINT (s->v2)); 01239 } 01240 01241 static void create_heap_refine (GtsEdge * e, GtsEHeap * heap) 01242 { 01243 gts_eheap_insert (heap, e); 01244 } 01245 01267 void gts_surface_refine (GtsSurface * surface, 01268 GtsKeyFunc cost_func, 01269 gpointer cost_data, 01270 GtsRefineFunc refine_func, 01271 gpointer refine_data, 01272 GtsStopFunc stop_func, 01273 gpointer stop_data) 01274 { 01275 GtsEHeap * heap; 01276 GtsEdge * e; 01277 gdouble top_cost; 01278 01279 g_return_if_fail (surface != NULL); 01280 g_return_if_fail (stop_func != NULL); 01281 01282 if (cost_func == NULL) 01283 cost_func = (GtsKeyFunc) edge_length2_inverse; 01284 if (refine_func == NULL) 01285 refine_func = (GtsRefineFunc) gts_segment_midvertex; 01286 01287 heap = gts_eheap_new (cost_func, cost_data); 01288 gts_eheap_freeze (heap); 01289 gts_surface_foreach_edge (surface, (GtsFunc) create_heap_refine, heap); 01290 gts_eheap_thaw (heap); 01291 while ((e = gts_eheap_remove_top (heap, &top_cost)) && 01292 !(*stop_func) (top_cost, 01293 gts_eheap_size (heap) + 01294 gts_edge_face_number (e, surface) + 2, 01295 stop_data)) 01296 midvertex_insertion (e, surface, heap, refine_func, refine_data, 01297 surface->vertex_class, surface->edge_class); 01298 gts_eheap_destroy (heap); 01299 } 01300 01301 static GSList * edge_triangles (GtsEdge * e1, GtsEdge * e) 01302 { 01303 GSList * i = e1->triangles; 01304 GSList * triangles = NULL; 01305 01306 while (i) { 01307 GtsTriangle * t = i->data; 01308 if (t->e1 == e || t->e2 == e || t->e3 == e) { 01309 GtsEdge * e2; 01310 GSList * j; 01311 if (t->e1 == e) { 01312 if (t->e2 == e1) 01313 e2 = t->e3; 01314 else 01315 e2 = t->e2; 01316 } 01317 else if (t->e2 == e) { 01318 if (t->e3 == e1) 01319 e2 = t->e1; 01320 else 01321 e2 = t->e3; 01322 } 01323 else { 01324 if (t->e2 == e1) 01325 e2 = t->e1; 01326 else 01327 e2 = t->e2; 01328 } 01329 j = e2->triangles; 01330 while (j) { 01331 GtsTriangle * t = j->data; 01332 if (t->e1 != e && t->e2 != e && t->e3 != e) 01333 triangles = g_slist_prepend (triangles, t); 01334 j = j->next; 01335 } 01336 } 01337 else 01338 triangles = g_slist_prepend (triangles, t); 01339 i = i->next; 01340 } 01341 return triangles; 01342 } 01343 01344 static void replace_vertex (GSList * i, GtsVertex * v1, GtsVertex * v) 01345 { 01346 while (i) { 01347 GtsSegment * s = i->data; 01348 if (s->v1 == v1) 01349 s->v1 = v; 01350 else 01351 s->v2 = v; 01352 i = i->next; 01353 } 01354 } 01355 01367 gboolean gts_edge_collapse_creates_fold (GtsEdge * e, 01368 GtsVertex * v, 01369 gdouble max) 01370 { 01371 GtsVertex * v1, * v2; 01372 GtsSegment * s; 01373 GSList * i; 01374 gboolean folded = FALSE; 01375 01376 g_return_val_if_fail (e != NULL, TRUE); 01377 g_return_val_if_fail (v != NULL, TRUE); 01378 01379 s = GTS_SEGMENT (e); 01380 v1 = s->v1; 01381 v2 = s->v2; 01382 replace_vertex (v1->segments, v1, v); 01383 replace_vertex (v2->segments, v2, v); 01384 01385 i = v1->segments; 01386 while (i && !folded) { 01387 GtsSegment * s = i->data; 01388 if (GTS_IS_EDGE (s)) { 01389 GtsEdge * e1 = GTS_EDGE (s); 01390 if (e1 != e) { 01391 GSList * triangles = edge_triangles (e1, e); 01392 folded = gts_triangles_are_folded (triangles, s->v1, s->v2, max); 01393 g_slist_free (triangles); 01394 } 01395 } 01396 i = i->next; 01397 } 01398 01399 i = v2->segments; 01400 while (i && !folded) { 01401 GtsSegment * s = i->data; 01402 if (GTS_IS_EDGE (s)) { 01403 GtsEdge * e1 = GTS_EDGE (s); 01404 if (e1 != e) { 01405 GSList * triangles = edge_triangles (e1, e); 01406 folded = gts_triangles_are_folded (triangles, s->v1, s->v2, max); 01407 g_slist_free (triangles); 01408 } 01409 } 01410 i = i->next; 01411 } 01412 #if 1 01413 if (!folded) { 01414 GSList * triangles = gts_vertex_triangles (v1, NULL); 01415 i = triangles = gts_vertex_triangles (v2, triangles); 01416 while (i && !folded) { 01417 GtsTriangle * t = i->data; 01418 if (t->e1 != e && t->e2 != e && t->e3 != e) { 01419 GtsEdge * e1 = gts_triangle_edge_opposite (t, v); 01420 g_assert (e1); 01421 folded = gts_triangles_are_folded (e1->triangles, 01422 GTS_SEGMENT (e1)->v1, 01423 GTS_SEGMENT (e1)->v2, 01424 max); 01425 } 01426 i = i->next; 01427 } 01428 g_slist_free (triangles); 01429 } 01430 #endif 01431 replace_vertex (v1->segments, v, v1); 01432 replace_vertex (v2->segments, v, v2); 01433 return folded; 01434 } 01435 01446 gboolean gts_edge_collapse_is_valid (GtsEdge * e) 01447 { 01448 GSList * i; 01449 01450 g_return_val_if_fail (e != NULL, FALSE); 01451 01452 i = GTS_SEGMENT (e)->v1->segments; 01453 while (i) { 01454 GtsEdge * e1 = i->data; 01455 if (e1 != e && GTS_IS_EDGE (e1)) { 01456 GtsEdge * e2 = NULL; 01457 GSList * j = GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e)->v1 ? 01458 GTS_SEGMENT (e1)->v2->segments : GTS_SEGMENT (e1)->v1->segments; 01459 while (j && !e2) { 01460 GtsEdge * e1 = j->data; 01461 if (GTS_IS_EDGE (e1) && 01462 (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e)->v2 || 01463 GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e)->v2)) 01464 e2 = e1; 01465 j = j->next; 01466 } 01467 if (e2 && !gts_triangle_use_edges (e, e1, e2)) 01468 return FALSE; 01469 } 01470 i = i->next; 01471 } 01472 01473 if (gts_edge_is_boundary (e, NULL)) { 01474 GtsTriangle * t = e->triangles->data; 01475 if (gts_edge_is_boundary (t->e1, NULL) && 01476 gts_edge_is_boundary (t->e2, NULL) && 01477 gts_edge_is_boundary (t->e3, NULL)) 01478 return FALSE; 01479 } 01480 else { 01481 if (gts_vertex_is_boundary (GTS_SEGMENT (e)->v1, NULL) && 01482 gts_vertex_is_boundary (GTS_SEGMENT (e)->v2, NULL)) 01483 return FALSE; 01484 if (gts_edge_belongs_to_tetrahedron (e)) 01485 return FALSE; 01486 } 01487 01488 return TRUE; 01489 } 01490 01491 #define HEAP_INSERT_EDGE(h, e) (GTS_OBJECT (e)->reserved = gts_eheap_insert (h, e)) 01492 #define HEAP_REMOVE_EDGE(h, e) (gts_eheap_remove (h, GTS_OBJECT (e)->reserved),\ 01493 GTS_OBJECT (e)->reserved = NULL) 01494 01495 static GtsVertex * edge_collapse (GtsEdge * e, 01496 GtsEHeap * heap, 01497 GtsCoarsenFunc coarsen_func, 01498 gpointer coarsen_data, 01499 GtsVertexClass * klass, 01500 gdouble maxcosine2) 01501 { 01502 GSList * i; 01503 GtsVertex * v1 = GTS_SEGMENT (e)->v1, * v2 = GTS_SEGMENT (e)->v2, * mid; 01504 01505 /* if the edge is degenerate (i.e. v1 == v2), destroy and return */ 01506 if (v1 == v2) { 01507 gts_object_destroy (GTS_OBJECT (e)); 01508 return NULL; 01509 } 01510 01511 if (!gts_edge_collapse_is_valid (e)) { 01512 GTS_OBJECT (e)->reserved = 01513 gts_eheap_insert_with_key (heap, e, G_MAXDOUBLE); 01514 return NULL; 01515 } 01516 01517 mid = (*coarsen_func) (e, klass, coarsen_data); 01518 01519 if (gts_edge_collapse_creates_fold (e, mid, maxcosine2)) { 01520 GTS_OBJECT (e)->reserved = 01521 gts_eheap_insert_with_key (heap, e, G_MAXDOUBLE); 01522 gts_object_destroy (GTS_OBJECT (mid)); 01523 return NULL; 01524 } 01525 01526 gts_object_destroy (GTS_OBJECT (e)); 01527 01528 gts_vertex_replace (v1, mid); 01529 gts_object_destroy (GTS_OBJECT (v1)); 01530 gts_vertex_replace (v2, mid); 01531 gts_object_destroy (GTS_OBJECT (v2)); 01532 01533 /* destroy duplicate edges */ 01534 i = mid->segments; 01535 while (i) { 01536 GtsEdge * e1 = i->data; 01537 GtsEdge * duplicate; 01538 while ((duplicate = gts_edge_is_duplicate (e1))) { 01539 gts_edge_replace (duplicate, GTS_EDGE (e1)); 01540 HEAP_REMOVE_EDGE (heap, duplicate); 01541 gts_object_destroy (GTS_OBJECT (duplicate)); 01542 } 01543 i = i->next; 01544 if (!e1->triangles) { 01545 /* e1 is the result of the collapse of one edge of a pair of identical 01546 faces (it should not happen unless duplicate triangles are present in 01547 the initial surface) */ 01548 g_warning ("file %s: line %d (%s): probably duplicate triangle.", 01549 __FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION); 01550 HEAP_REMOVE_EDGE (heap, e1); 01551 gts_object_destroy (GTS_OBJECT (e1)); 01552 if (i == NULL) /* mid has been destroyed */ 01553 mid = NULL; 01554 } 01555 } 01556 01557 return mid; 01558 } 01559 01560 /* 01561 * I don't see where this code is ever used, but keep it for a bit 01562 * in case it is needed for debugging 01563 */ 01564 #ifdef GTS_NEED_UPDATE_CLOSEST_NEIGHBORS 01565 static void update_closest_neighbors (GtsVertex * v, GtsEHeap * heap) 01566 { 01567 GSList * i = v->segments; 01568 01569 while (i) { 01570 GtsSegment * s = i->data; 01571 if (GTS_IS_EDGE (s)) { 01572 HEAP_REMOVE_EDGE (heap, GTS_EDGE (s)); 01573 HEAP_INSERT_EDGE (heap, GTS_EDGE (s)); 01574 } 01575 i = i->next; 01576 } 01577 } 01578 #endif 01579 01580 static void update_2nd_closest_neighbors (GtsVertex * v, GtsEHeap * heap) 01581 { 01582 GSList * i = v->segments; 01583 GSList * list = NULL; 01584 01585 while (i) { 01586 GtsSegment * s = i->data; 01587 if (GTS_IS_EDGE (s)) { 01588 GtsVertex * v1 = s->v1 == v ? s->v2 : s->v1; 01589 GSList * j = v1->segments; 01590 while (j) { 01591 GtsSegment * s1 = j->data; 01592 if (GTS_IS_EDGE (s1) && !g_slist_find (list, s1)) 01593 list = g_slist_prepend (list, s1); 01594 j = j->next; 01595 } 01596 } 01597 i = i->next; 01598 } 01599 01600 i = list; 01601 while (i) { 01602 GtsEdge * e = i->data; 01603 HEAP_REMOVE_EDGE (heap, e); 01604 HEAP_INSERT_EDGE (heap, e); 01605 i = i->next; 01606 } 01607 01608 g_slist_free (list); 01609 } 01610 01611 static gdouble edge_length2 (GtsEdge * e) 01612 { 01613 return gts_point_distance2 (GTS_POINT (GTS_SEGMENT (e)->v1), 01614 GTS_POINT (GTS_SEGMENT (e)->v2)); 01615 } 01616 01617 static void create_heap_coarsen (GtsEdge * e, GtsEHeap * heap) 01618 { 01619 HEAP_INSERT_EDGE (heap, e); 01620 } 01621 01646 void gts_surface_coarsen (GtsSurface * surface, 01647 GtsKeyFunc cost_func, 01648 gpointer cost_data, 01649 GtsCoarsenFunc coarsen_func, 01650 gpointer coarsen_data, 01651 GtsStopFunc stop_func, 01652 gpointer stop_data, 01653 gdouble minangle) 01654 { 01655 GtsEHeap * heap; 01656 GtsEdge * e; 01657 gdouble top_cost; 01658 gdouble maxcosine2; 01659 01660 g_return_if_fail (surface != NULL); 01661 g_return_if_fail (stop_func != NULL); 01662 01663 if (cost_func == NULL) 01664 cost_func = (GtsKeyFunc) edge_length2; 01665 if (coarsen_func == NULL) 01666 coarsen_func = (GtsCoarsenFunc) gts_segment_midvertex; 01667 01668 heap = gts_eheap_new (cost_func, cost_data); 01669 maxcosine2 = cos (minangle); maxcosine2 *= maxcosine2; 01670 01671 gts_eheap_freeze (heap); 01672 gts_surface_foreach_edge (surface, (GtsFunc) create_heap_coarsen, heap); 01673 gts_eheap_thaw (heap); 01674 /* we want to control edge destruction manually */ 01675 gts_allow_floating_edges = TRUE; 01676 while ((e = gts_eheap_remove_top (heap, &top_cost)) && 01677 (top_cost < G_MAXDOUBLE) && 01678 !(*stop_func) (top_cost, gts_eheap_size (heap) - 01679 gts_edge_face_number (e, surface), stop_data)) 01680 { 01681 GtsVertex * v = edge_collapse (e, heap, coarsen_func, coarsen_data, 01682 surface->vertex_class, maxcosine2); 01683 if (v != NULL) 01684 update_2nd_closest_neighbors (v, heap); 01685 } 01686 gts_allow_floating_edges = FALSE; 01687 01688 /* set reserved field of remaining edges back to NULL */ 01689 if (e) GTS_OBJECT (e)->reserved = NULL; 01690 gts_eheap_foreach (heap, (GFunc) gts_object_reset_reserved, NULL); 01691 01692 gts_eheap_destroy (heap); 01693 } 01694 01708 gboolean gts_coarsen_stop_number (gdouble cost, 01709 guint nedge, 01710 guint * min_number) 01711 { 01712 g_return_val_if_fail (min_number != NULL, TRUE); 01713 01714 if (nedge < *min_number) 01715 return TRUE; 01716 return FALSE; 01717 } 01718 01731 gboolean gts_coarsen_stop_cost (gdouble cost, 01732 guint nedge, 01733 gdouble * max_cost) 01734 { 01735 g_return_val_if_fail (max_cost != NULL, TRUE); 01736 01737 if (cost > *max_cost) 01738 return TRUE; 01739 return FALSE; 01740 } 01741 01742 #define GTS_M_ICOSAHEDRON_X /* sqrt(sqrt(5)+1)/sqrt(2*sqrt(5)) */ \ 01743 0.850650808352039932181540497063011072240401406 01744 #define GTS_M_ICOSAHEDRON_Y /* sqrt(2)/sqrt(5+sqrt(5)) */ \ 01745 0.525731112119133606025669084847876607285497935 01746 #define GTS_M_ICOSAHEDRON_Z 0.0 01747 01748 static guint generate_icosahedron (GtsSurface * s) 01749 { 01750 GtsVertex * v01 = gts_vertex_new (s->vertex_class, 01751 +GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y); 01752 GtsVertex * v02 = gts_vertex_new (s->vertex_class, 01753 +GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z); 01754 GtsVertex * v03 = gts_vertex_new (s->vertex_class, 01755 +GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X); 01756 GtsVertex * v04 = gts_vertex_new (s->vertex_class, 01757 +GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X); 01758 GtsVertex * v05 = gts_vertex_new (s->vertex_class, 01759 +GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z); 01760 GtsVertex * v06 = gts_vertex_new (s->vertex_class, 01761 +GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y); 01762 GtsVertex * v07 = gts_vertex_new (s->vertex_class, 01763 -GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X); 01764 GtsVertex * v08 = gts_vertex_new (s->vertex_class, 01765 +GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y); 01766 GtsVertex * v09 = gts_vertex_new (s->vertex_class, 01767 -GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z); 01768 GtsVertex * v10 = gts_vertex_new (s->vertex_class, 01769 -GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X); 01770 GtsVertex * v11 = gts_vertex_new (s->vertex_class, 01771 -GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z); 01772 GtsVertex * v12 = gts_vertex_new (s->vertex_class, 01773 +GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y); 01774 01775 GtsEdge * e01 = gts_edge_new (s->edge_class, v01, v02); 01776 GtsEdge * e02 = gts_edge_new (s->edge_class, v03, v02); 01777 GtsEdge * e03 = gts_edge_new (s->edge_class, v01, v03); 01778 GtsEdge * e04 = gts_edge_new (s->edge_class, v04, v05); 01779 GtsEdge * e05 = gts_edge_new (s->edge_class, v02, v05); 01780 GtsEdge * e06 = gts_edge_new (s->edge_class, v04, v02); 01781 GtsEdge * e07 = gts_edge_new (s->edge_class, v06, v07); 01782 GtsEdge * e08 = gts_edge_new (s->edge_class, v04, v07); 01783 GtsEdge * e09 = gts_edge_new (s->edge_class, v06, v04); 01784 GtsEdge * e10 = gts_edge_new (s->edge_class, v08, v03); 01785 GtsEdge * e11 = gts_edge_new (s->edge_class, v03, v05); 01786 GtsEdge * e12 = gts_edge_new (s->edge_class, v08, v05); 01787 GtsEdge * e13 = gts_edge_new (s->edge_class, v06, v09); 01788 GtsEdge * e14 = gts_edge_new (s->edge_class, v07, v09); 01789 GtsEdge * e15 = gts_edge_new (s->edge_class, v08, v10); 01790 GtsEdge * e16 = gts_edge_new (s->edge_class, v03, v10); 01791 GtsEdge * e17 = gts_edge_new (s->edge_class, v06, v01); 01792 GtsEdge * e18 = gts_edge_new (s->edge_class, v01, v09); 01793 GtsEdge * e19 = gts_edge_new (s->edge_class, v08, v11); 01794 GtsEdge * e20 = gts_edge_new (s->edge_class, v10, v11); 01795 GtsEdge * e21 = gts_edge_new (s->edge_class, v06, v02); 01796 GtsEdge * e22 = gts_edge_new (s->edge_class, v12, v11); 01797 GtsEdge * e23 = gts_edge_new (s->edge_class, v12, v08); 01798 GtsEdge * e24 = gts_edge_new (s->edge_class, v12, v07); 01799 GtsEdge * e25 = gts_edge_new (s->edge_class, v07, v11); 01800 GtsEdge * e26 = gts_edge_new (s->edge_class, v12, v04); 01801 GtsEdge * e27 = gts_edge_new (s->edge_class, v09, v11); 01802 GtsEdge * e28 = gts_edge_new (s->edge_class, v10, v09); 01803 GtsEdge * e29 = gts_edge_new (s->edge_class, v12, v05); 01804 GtsEdge * e30 = gts_edge_new (s->edge_class, v01, v10); 01805 01806 gts_surface_add_face (s, gts_face_new (s->face_class, e01, e02, e03)); 01807 gts_surface_add_face (s, gts_face_new (s->face_class, e04, e05, e06)); 01808 gts_surface_add_face (s, gts_face_new (s->face_class, e07, e08, e09)); 01809 gts_surface_add_face (s, gts_face_new (s->face_class, e10, e11, e12)); 01810 gts_surface_add_face (s, gts_face_new (s->face_class, e13, e14, e07)); 01811 gts_surface_add_face (s, gts_face_new (s->face_class, e15, e16, e10)); 01812 gts_surface_add_face (s, gts_face_new (s->face_class, e17, e18, e13)); 01813 gts_surface_add_face (s, gts_face_new (s->face_class, e19, e20, e15)); 01814 gts_surface_add_face (s, gts_face_new (s->face_class, e21, e01, e17)); 01815 gts_surface_add_face (s, gts_face_new (s->face_class, e22, e19, e23)); 01816 gts_surface_add_face (s, gts_face_new (s->face_class, e09, e06, e21)); 01817 gts_surface_add_face (s, gts_face_new (s->face_class, e24, e25, e22)); 01818 gts_surface_add_face (s, gts_face_new (s->face_class, e26, e08, e24)); 01819 gts_surface_add_face (s, gts_face_new (s->face_class, e20, e27, e28)); 01820 gts_surface_add_face (s, gts_face_new (s->face_class, e29, e04, e26)); 01821 gts_surface_add_face (s, gts_face_new (s->face_class, e14, e27, e25)); 01822 gts_surface_add_face (s, gts_face_new (s->face_class, e23, e12, e29)); 01823 gts_surface_add_face (s, gts_face_new (s->face_class, e02, e05, e11)); 01824 gts_surface_add_face (s, gts_face_new (s->face_class, e30, e28, e18)); 01825 gts_surface_add_face (s, gts_face_new (s->face_class, e03, e16, e30)); 01826 01827 return 0; 01828 } 01829 01830 static GtsVertex * unit_sphere_arc_midvertex (GtsSegment * s, 01831 GtsVertexClass * vertex_class) 01832 { 01833 GtsPoint * p1, * p2; 01834 gdouble x, y, z, norm; 01835 01836 p1 = GTS_POINT (s->v1); p2 = GTS_POINT (s->v2); 01837 01838 x = 0.5*(p1->x + p2->x); 01839 y = 0.5*(p1->y + p2->y); 01840 z = 0.5*(p1->z + p2->z); 01841 01842 norm = x*x + y*y + z*z; 01843 norm = sqrt (norm); 01844 01845 x /= norm; y /= norm; z /= norm; 01846 01847 return gts_vertex_new (vertex_class, x, y, z); 01848 } 01849 01850 static void tessellate_face (GtsFace * f, 01851 GtsSurface * s, 01852 GtsRefineFunc refine_func, 01853 gpointer refine_data, 01854 GtsVertexClass * vertex_class, 01855 GtsEdgeClass * edge_class) 01856 { 01857 GtsTriangle * t; 01858 GtsEdge * e1, * e2, * e3; /* former edges */ 01859 GtsVertex * v1, * v2, * v3; /* initial vertices */ 01860 GtsVertex * v4, * v5, * v6; /* new vertices */ 01861 GtsEdge * e56, * e64, * e45; /* new inside edges */ 01862 GtsEdge * e24, * e34, * e35, * e15, * e16, * e26; /* new border edges */ 01863 GSList * dum; 01864 GtsEdge * edum; 01865 01866 t = GTS_TRIANGLE (f); 01867 e1 = t->e1; e2 = t->e2; e3 = t->e3; 01868 01869 if (GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e2)->v1) { 01870 v1 = GTS_SEGMENT (e2)->v2; 01871 v2 = GTS_SEGMENT (e1)->v1; 01872 v3 = GTS_SEGMENT (e1)->v2; 01873 } 01874 else if (GTS_SEGMENT (e1)->v2 == GTS_SEGMENT (e2)->v2) { 01875 v1 = GTS_SEGMENT (e2)->v1; 01876 v2 = GTS_SEGMENT (e1)->v1; 01877 v3 = GTS_SEGMENT (e1)->v2; 01878 } 01879 else if (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e2)->v1) { 01880 v1 = GTS_SEGMENT (e2)->v2; 01881 v2 = GTS_SEGMENT (e1)->v2; 01882 v3 = GTS_SEGMENT (e1)->v1; 01883 } 01884 else if (GTS_SEGMENT (e1)->v1 == GTS_SEGMENT (e2)->v2) { 01885 v1 = GTS_SEGMENT (e2)->v1; 01886 v2 = GTS_SEGMENT (e1)->v2; 01887 v3 = GTS_SEGMENT (e1)->v1; 01888 } 01889 else { 01890 v1 = v2 = v3 = NULL; 01891 g_assert_not_reached (); 01892 } 01893 01894 e1->triangles = g_slist_remove (e1->triangles, t); 01895 e2->triangles = g_slist_remove (e2->triangles, t); 01896 e3->triangles = g_slist_remove (e3->triangles, t); 01897 01898 if (GTS_OBJECT (e1)->reserved) { 01899 dum = (GTS_OBJECT (e1)->reserved); 01900 e24 = dum->data; 01901 e34 = dum->next->data; 01902 v4 = GTS_SEGMENT (e24)->v2; 01903 if (GTS_SEGMENT (e24)->v1 == v3) { 01904 edum = e34; e34 = e24; e24 = edum; 01905 } 01906 } 01907 else { 01908 v4 = (*refine_func) (e1, vertex_class, refine_data); 01909 e24 = gts_edge_new (edge_class, v2, v4); 01910 e34 = gts_edge_new (edge_class, v3, v4); 01911 dum = g_slist_append (NULL, e24); 01912 dum = g_slist_append (dum, e34); 01913 GTS_OBJECT (e1)->reserved = dum; 01914 } 01915 if (GTS_OBJECT (e2)->reserved) { 01916 dum = (GTS_OBJECT (e2)->reserved); 01917 e35 = dum->data; 01918 e15 = dum->next->data; 01919 v5 = GTS_SEGMENT (e35)->v2; 01920 if (GTS_SEGMENT (e35)->v1 == v1) { 01921 edum = e15; e15 = e35; e35 = edum; 01922 } 01923 } 01924 else { 01925 v5 = (*refine_func) (e2, vertex_class, refine_data); 01926 e35 = gts_edge_new (edge_class, v3, v5); 01927 e15 = gts_edge_new (edge_class, v1, v5); 01928 dum = g_slist_append (NULL, e35); 01929 dum = g_slist_append (dum, e15); 01930 GTS_OBJECT (e2)->reserved = dum; 01931 } 01932 if (GTS_OBJECT (e3)->reserved) { 01933 dum = (GTS_OBJECT (e3)->reserved); 01934 e16 = dum->data; 01935 e26 = dum->next->data; 01936 v6 = GTS_SEGMENT (e16)->v2; 01937 if (GTS_SEGMENT (e16)->v1 == v2) { 01938 edum = e16; e16 = e26; e26 = edum; 01939 } 01940 } 01941 else { 01942 v6 = (*refine_func) (e3, vertex_class, refine_data); 01943 e16 = gts_edge_new (edge_class, v1, v6); 01944 e26 = gts_edge_new (edge_class, v2, v6); 01945 dum = g_slist_append (NULL, e16); 01946 dum = g_slist_append (dum, e26); 01947 GTS_OBJECT (e3)->reserved = dum; 01948 } 01949 01950 if (e1->triangles == NULL) { 01951 g_slist_free (GTS_OBJECT (e1)->reserved); 01952 GTS_OBJECT (e1)->reserved = NULL; 01953 gts_object_destroy (GTS_OBJECT (e1)); 01954 e1 = NULL; 01955 } 01956 if (e2->triangles == NULL) { 01957 g_slist_free (GTS_OBJECT (e2)->reserved); 01958 GTS_OBJECT (e2)->reserved = NULL; 01959 gts_object_destroy (GTS_OBJECT (e2)); 01960 e2 = NULL; 01961 } 01962 if (e3->triangles == NULL) { 01963 g_slist_free (GTS_OBJECT (e3)->reserved); 01964 GTS_OBJECT (e3)->reserved = NULL; 01965 gts_object_destroy (GTS_OBJECT (e3)); 01966 e3 = NULL; 01967 } 01968 01969 e56 = gts_edge_new (edge_class, v5, v6); 01970 e64 = gts_edge_new (edge_class, v6, v4); 01971 e45 = gts_edge_new (edge_class, v4, v5); 01972 t->e1 = e56; e56->triangles = g_slist_prepend (e56->triangles, t); 01973 t->e2 = e64; e64->triangles = g_slist_prepend (e64->triangles, t); 01974 t->e3 = e45; e45->triangles = g_slist_prepend (e45->triangles, t); 01975 01976 gts_surface_add_face (s, gts_face_new (s->face_class, e16, e56, e15)); 01977 gts_surface_add_face (s, gts_face_new (s->face_class, e26, e24, e64)); 01978 gts_surface_add_face (s, gts_face_new (s->face_class, e45, e34, e35)); 01979 } 01980 01981 static void create_array_tessellate (GtsFace * f, GPtrArray * array) 01982 { 01983 g_ptr_array_add (array, f); 01984 } 01985 02002 void gts_surface_tessellate (GtsSurface * s, 02003 GtsRefineFunc refine_func, 02004 gpointer refine_data) 02005 { 02006 GPtrArray * array; 02007 guint i; 02008 02009 g_return_if_fail (s != NULL); 02010 02011 if (refine_func == NULL) /* tessellate_surface == geodesate_surface */ 02012 refine_func = (GtsRefineFunc) unit_sphere_arc_midvertex; 02013 02014 array = g_ptr_array_new (); 02015 gts_surface_foreach_face (s, (GtsFunc) create_array_tessellate, array); 02016 for(i = 0; i < array->len; i++) 02017 tessellate_face (g_ptr_array_index (array, i), 02018 s, refine_func, refine_data, 02019 s->vertex_class, s->edge_class); 02020 g_ptr_array_free (array, TRUE); 02021 } 02022 02035 GtsSurface * gts_surface_generate_sphere (GtsSurface * s, 02036 guint geodesation_order) 02037 { 02038 guint cgo; 02039 02040 g_return_val_if_fail (s != NULL, NULL); 02041 g_return_val_if_fail (geodesation_order != 0, NULL); 02042 02043 generate_icosahedron (s); 02044 02045 for (cgo = 1; cgo < geodesation_order; cgo++) 02046 gts_surface_tessellate (s, NULL, NULL); 02047 02048 return s; 02049 } 02050 02051 static void foreach_vertex_copy (GtsPoint * p, GtsVertexClass * klass) 02052 { 02053 GTS_OBJECT (p)->reserved = gts_vertex_new (klass, p->x, p->y, p->z); 02054 } 02055 02056 static void foreach_edge_copy (GtsSegment * s, GtsEdgeClass * klass) 02057 { 02058 GTS_OBJECT (s)->reserved = gts_edge_new (klass, 02059 GTS_OBJECT (s->v1)->reserved, 02060 GTS_OBJECT (s->v2)->reserved); 02061 } 02062 02063 static void foreach_face_copy (GtsTriangle * t, 02064 GtsSurface * s) 02065 { 02066 gts_surface_add_face (s, gts_face_new (s->face_class, 02067 GTS_OBJECT (t->e1)->reserved, 02068 GTS_OBJECT (t->e2)->reserved, 02069 GTS_OBJECT (t->e3)->reserved)); 02070 } 02071 02081 GtsSurface * gts_surface_copy (GtsSurface * s1, GtsSurface * s2) 02082 { 02083 g_return_val_if_fail (s1 != NULL, NULL); 02084 g_return_val_if_fail (s2 != NULL, NULL); 02085 02086 gts_surface_foreach_vertex (s2, (GtsFunc) foreach_vertex_copy, 02087 s1->vertex_class); 02088 gts_surface_foreach_edge (s2, (GtsFunc) foreach_edge_copy, s1->edge_class); 02089 gts_surface_foreach_face (s2, (GtsFunc) foreach_face_copy, s1); 02090 02091 gts_surface_foreach_vertex (s2, (GtsFunc) gts_object_reset_reserved, NULL); 02092 gts_surface_foreach_edge (s2, (GtsFunc) gts_object_reset_reserved, NULL); 02093 02094 return s1; 02095 } 02096 02097 static void merge_foreach_face (GtsFace * f, 02098 GtsSurface * s) 02099 { 02100 gts_surface_add_face (s, f); 02101 } 02102 02111 void gts_surface_merge (GtsSurface * s, GtsSurface * with) 02112 { 02113 g_return_if_fail (s != NULL); 02114 g_return_if_fail (with != NULL); 02115 02116 gts_surface_foreach_face (with, (GtsFunc) merge_foreach_face, s); 02117 } 02118 02119 static void manifold_foreach_edge (GtsEdge * e, gpointer * data) 02120 { 02121 gboolean * is_manifold = data[0]; 02122 02123 if (*is_manifold) { 02124 if (gts_edge_face_number (e, data[1]) > 2) 02125 *is_manifold = FALSE; 02126 } 02127 } 02128 02135 gboolean gts_surface_is_manifold (GtsSurface * s) 02136 { 02137 gboolean is_manifold = TRUE; 02138 gpointer data[2]; 02139 02140 g_return_val_if_fail (s != NULL, FALSE); 02141 02142 data[0] = &is_manifold; 02143 data[1] = s; 02144 gts_surface_foreach_edge (s, (GtsFunc) manifold_foreach_edge, data); 02145 return is_manifold; 02146 } 02147 02148 static void closed_foreach_edge (GtsEdge * e, gpointer * data) 02149 { 02150 gboolean * is_closed = data[0]; 02151 02152 if (*is_closed) { 02153 if (gts_edge_face_number (e, data[1]) != 2) 02154 *is_closed = FALSE; 02155 } 02156 } 02157 02165 gboolean gts_surface_is_closed (GtsSurface * s) 02166 { 02167 gboolean is_closed = TRUE; 02168 gpointer data[2]; 02169 02170 g_return_val_if_fail (s != NULL, FALSE); 02171 02172 data[0] = &is_closed; 02173 data[1] = s; 02174 gts_surface_foreach_edge (s, (GtsFunc) closed_foreach_edge, data); 02175 return is_closed; 02176 } 02177 02178 static void orientable_foreach_edge (GtsEdge * e, gpointer * data) 02179 { 02180 gboolean * is_orientable = data[0]; 02181 02182 if (*is_orientable) { 02183 GtsSurface * surface = data[1]; 02184 GtsFace * f1 = NULL, * f2 = NULL; 02185 GSList * i = e->triangles; 02186 while (i && *is_orientable) { 02187 GtsFace * f = i->data; 02188 if (GTS_IS_FACE (f) && gts_face_has_parent_surface (f, surface)) { 02189 if (!f1) f1 = f; 02190 else if (!f2) f2 = f; 02191 else *is_orientable = FALSE; 02192 } 02193 i = i->next; 02194 } 02195 if (f1 && f2 && !gts_triangles_are_compatible (GTS_TRIANGLE (f1), 02196 GTS_TRIANGLE (f2), e)) 02197 *is_orientable = FALSE; 02198 } 02199 } 02200 02209 gboolean gts_surface_is_orientable (GtsSurface * s) 02210 { 02211 gboolean is_orientable = TRUE; 02212 gpointer data[2]; 02213 02214 g_return_val_if_fail (s != NULL, FALSE); 02215 02216 data[0] = &is_orientable; 02217 data[1] = s; 02218 gts_surface_foreach_edge (s, (GtsFunc) orientable_foreach_edge, data); 02219 return is_orientable; 02220 } 02221 02222 static void volume_foreach_face (GtsTriangle * t, 02223 gdouble * volume) 02224 { 02225 GtsVertex * va, * vb, * vc; 02226 GtsPoint * pa, * pb, * pc; 02227 02228 gts_triangle_vertices (t, &va, &vb, &vc); 02229 pa = GTS_POINT (va); 02230 pb = GTS_POINT (vb); 02231 pc = GTS_POINT (vc); 02232 02233 *volume += (pa->x * (pb->y * pc->z - pb->z * pc->y) + 02234 pb->x * (pc->y * pa->z - pc->z * pa->y) + 02235 pc->x * (pa->y * pb->z - pa->z * pb->y)); 02236 } 02237 02245 gdouble gts_surface_volume (GtsSurface * s) 02246 { 02247 gdouble volume = 0.0; 02248 02249 g_return_val_if_fail (s != NULL, 0.0); 02250 02251 gts_surface_foreach_face (s, (GtsFunc) volume_foreach_face, &volume); 02252 02253 return volume/6.; 02254 } 02255 02256 static void center_of_mass_foreach_face (GtsTriangle * t, 02257 gpointer * data) 02258 { 02259 GtsVertex * v1, * v2, * v3; 02260 GtsPoint * p1, * p2, * p3; 02261 gdouble x1, y1, z1, x2, y2, z2, nx, ny, nz; 02262 gdouble * volume = data[0]; 02263 gdouble * cm = data[1]; 02264 02265 gts_triangle_vertices (t, &v1, &v2, &v3); 02266 p1 = GTS_POINT (v1); 02267 p2 = GTS_POINT (v2); 02268 p3 = GTS_POINT (v3); 02269 02270 x1 = p2->x - p1->x; 02271 y1 = p2->y - p1->y; 02272 z1 = p2->z - p1->z; 02273 02274 x2 = p3->x - p1->x; 02275 y2 = p3->y - p1->y; 02276 z2 = p3->z - p1->z; 02277 02278 nx = y1*z2 - z1*y2; 02279 ny = z1*x2 - x1*z2; 02280 nz = x1*y2 - y1*x2; 02281 02282 cm[0] += nx*(p1->x*p1->x + p2->x*p2->x + p3->x*p3->x + 02283 p1->x*p2->x + p1->x*p3->x + p2->x*p3->x); 02284 cm[1] += ny*(p1->y*p1->y + p2->y*p2->y + p3->y*p3->y + 02285 p1->y*p2->y + p1->y*p3->y + p2->y*p3->y); 02286 cm[2] += nz*(p1->z*p1->z + p2->z*p2->z + p3->z*p3->z + 02287 p1->z*p2->z + p1->z*p3->z + p2->z*p3->z); 02288 02289 *volume += nx*(p1->x + p2->x + p3->x); 02290 } 02291 02292 02302 gdouble gts_surface_center_of_mass (GtsSurface * s, 02303 GtsVector cm) 02304 { 02305 gdouble volume = 0.; 02306 gpointer data[2]; 02307 02308 g_return_val_if_fail (s != NULL, 0.0); 02309 02310 data[0] = &volume; 02311 data[1] = &(cm[0]); 02312 cm[0] = cm[1] = cm[2] = 0.; 02313 gts_surface_foreach_face (s, (GtsFunc) center_of_mass_foreach_face, data); 02314 02315 if (volume != 0.) { 02316 cm[0] /= 4.*volume; 02317 cm[1] /= 4.*volume; 02318 cm[2] /= 4.*volume; 02319 } 02320 02321 return volume/6.; 02322 } 02323 02324 static void center_of_area_foreach_face (GtsTriangle * t, 02325 gpointer * data) 02326 { 02327 GtsVertex * v1, * v2, * v3; 02328 GtsPoint * p1, * p2, * p3; 02329 gdouble a; 02330 gdouble * area = data[0]; 02331 gdouble * cm = data[1]; 02332 02333 gts_triangle_vertices (t, &v1, &v2, &v3); 02334 p1 = GTS_POINT (v1); 02335 p2 = GTS_POINT (v2); 02336 p3 = GTS_POINT (v3); 02337 02338 a = gts_triangle_area (t); 02339 cm[0] += a*(p1->x + p2->x + p3->x); 02340 cm[1] += a*(p1->y + p2->y + p3->y); 02341 cm[2] += a*(p1->z + p2->z + p3->z); 02342 *area += a; 02343 } 02344 02345 02355 gdouble gts_surface_center_of_area (GtsSurface * s, 02356 GtsVector cm) 02357 { 02358 gdouble area = 0.; 02359 gpointer data[2]; 02360 02361 g_return_val_if_fail (s != NULL, 0.0); 02362 02363 data[0] = &area; 02364 data[1] = &(cm[0]); 02365 cm[0] = cm[1] = cm[2] = 0.; 02366 gts_surface_foreach_face (s, (GtsFunc) center_of_area_foreach_face, data); 02367 02368 if (area != 0.) { 02369 cm[0] /= 3.*area; 02370 cm[1] /= 3.*area; 02371 cm[2] /= 3.*area; 02372 } 02373 02374 return area; 02375 } 02376 02377 static void number_foreach (gpointer data, guint * n) 02378 { 02379 (*n)++; 02380 } 02381 02388 guint gts_surface_vertex_number (GtsSurface * s) 02389 { 02390 guint n = 0; 02391 02392 g_return_val_if_fail (s != NULL, 0); 02393 02394 gts_surface_foreach_vertex (s, (GtsFunc) number_foreach, &n); 02395 02396 return n; 02397 } 02398 02405 guint gts_surface_edge_number (GtsSurface * s) 02406 { 02407 guint n = 0; 02408 02409 g_return_val_if_fail (s != NULL, 0); 02410 02411 gts_surface_foreach_edge (s, (GtsFunc) number_foreach, &n); 02412 02413 return n; 02414 } 02415 02422 guint gts_surface_face_number (GtsSurface * s) 02423 { 02424 g_return_val_if_fail (s != NULL, 0); 02425 02426 #ifdef USE_SURFACE_BTREE 02427 return g_tree_nnodes (s->faces); 02428 #else /* not USE_SURFACE_BTREE */ 02429 return g_hash_table_size (s->faces); 02430 #endif /* not USE_SURFACE_BTREE */ 02431 } 02432 02433 static void build_list_face (GtsTriangle * t, GSList ** list) 02434 { 02435 *list = g_slist_prepend (*list, gts_bbox_triangle (gts_bbox_class (), t)); 02436 } 02437 02438 static void build_list_boundary (GtsEdge * e, GSList ** list) 02439 { 02440 if (gts_edge_is_boundary (e, NULL)) 02441 *list = g_slist_prepend (*list, gts_bbox_segment (gts_bbox_class (), 02442 GTS_SEGMENT (e))); 02443 } 02444 02460 void gts_surface_distance (GtsSurface * s1, GtsSurface * s2, gdouble delta, 02461 GtsRange * face_range, GtsRange * boundary_range) 02462 { 02463 GNode * face_tree, * boundary_tree; 02464 GSList * bboxes; 02465 02466 g_return_if_fail (s1 != NULL); 02467 g_return_if_fail (s2 != NULL); 02468 g_return_if_fail (delta > 0. && delta < 1.); 02469 g_return_if_fail (face_range != NULL); 02470 g_return_if_fail (boundary_range != NULL); 02471 02472 bboxes = NULL; 02473 gts_surface_foreach_face (s2, (GtsFunc) build_list_face, &bboxes); 02474 if (bboxes != NULL) { 02475 face_tree = gts_bb_tree_new (bboxes); 02476 g_slist_free (bboxes); 02477 02478 gts_bb_tree_surface_distance (face_tree, s1, 02479 (GtsBBoxDistFunc) gts_point_triangle_distance, 02480 delta, face_range); 02481 gts_bb_tree_destroy (face_tree, TRUE); 02482 02483 bboxes = NULL; 02484 gts_surface_foreach_edge (s2, (GtsFunc) build_list_boundary, &bboxes); 02485 if (bboxes != NULL) { 02486 boundary_tree = gts_bb_tree_new (bboxes); 02487 g_slist_free (bboxes); 02488 02489 gts_bb_tree_surface_boundary_distance (boundary_tree, 02490 s1, 02491 (GtsBBoxDistFunc) gts_point_segment_distance, 02492 delta, boundary_range); 02493 gts_bb_tree_destroy (boundary_tree, TRUE); 02494 } 02495 else 02496 gts_range_reset (boundary_range); 02497 } 02498 else { 02499 gts_range_reset (face_range); 02500 gts_range_reset (boundary_range); 02501 } 02502 } 02503 02504 static void surface_boundary (GtsEdge * e, gpointer * data) 02505 { 02506 GSList ** list = data[0]; 02507 02508 if (gts_edge_is_boundary (e, data[1])) 02509 *list = g_slist_prepend (*list, e); 02510 } 02511 02518 GSList * gts_surface_boundary (GtsSurface * surface) 02519 { 02520 GSList * list = NULL; 02521 gpointer data[2]; 02522 02523 g_return_val_if_fail (surface != NULL, NULL); 02524 02525 data[0] = &list; 02526 data[1] = surface; 02527 gts_surface_foreach_edge (surface, (GtsFunc) surface_boundary, data); 02528 02529 return list; 02530 } 02531 02532 struct _GtsSurfaceTraverse { 02533 GtsFifo * q; 02534 GtsSurface * s; 02535 }; 02536 02545 GtsSurfaceTraverse * gts_surface_traverse_new (GtsSurface * s, 02546 GtsFace * f) 02547 { 02548 GtsSurfaceTraverse * t; 02549 02550 g_return_val_if_fail (s != NULL, NULL); 02551 g_return_val_if_fail (f != NULL, NULL); 02552 g_return_val_if_fail (gts_face_has_parent_surface (f, s), NULL); 02553 02554 t = g_malloc (sizeof (GtsSurfaceTraverse)); 02555 t->q = gts_fifo_new (); 02556 t->s = s; 02557 GTS_OBJECT (f)->reserved = GUINT_TO_POINTER (1); 02558 gts_fifo_push (t->q, f); 02559 return t; 02560 } 02561 02562 static void push_neighbor (GtsFace * v, gpointer * data) 02563 { 02564 if (!GTS_OBJECT (v)->reserved) { 02565 GTS_OBJECT (v)->reserved = 02566 GUINT_TO_POINTER (GPOINTER_TO_UINT (GTS_OBJECT (data[1])->reserved) + 1); 02567 gts_fifo_push (data[0], v); 02568 } 02569 } 02570 02581 GtsFace * gts_surface_traverse_next (GtsSurfaceTraverse * t, 02582 guint * level) 02583 { 02584 GtsFace * u; 02585 02586 g_return_val_if_fail (t != NULL, NULL); 02587 02588 u = gts_fifo_pop (t->q); 02589 if (u) { 02590 gpointer data[2]; 02591 02592 if (level) 02593 *level = GPOINTER_TO_UINT (GTS_OBJECT (u)->reserved); 02594 data[0] = t->q; 02595 data[1] = u; 02596 gts_face_foreach_neighbor (u, t->s, (GtsFunc) push_neighbor, data); 02597 } 02598 return u; 02599 } 02600 02607 void gts_surface_traverse_destroy (GtsSurfaceTraverse * t) 02608 { 02609 g_return_if_fail (t != NULL); 02610 02611 gts_surface_foreach_face (t->s, (GtsFunc) gts_object_reset_reserved, NULL); 02612 gts_fifo_destroy (t->q); 02613 g_free (t); 02614 } 02615 02616 static void traverse_manifold (GtsTriangle * t, GtsSurface * s) 02617 { 02618 if (g_slist_length (GTS_FACE (t)->surfaces) > 1) 02619 return; 02620 02621 gts_surface_add_face (s, GTS_FACE (t)); 02622 if (g_slist_length (t->e1->triangles) == 2) { 02623 if (t->e1->triangles->data != t) 02624 traverse_manifold (t->e1->triangles->data, s); 02625 else 02626 traverse_manifold (t->e1->triangles->next->data, s); 02627 } 02628 if (g_slist_length (t->e2->triangles) == 2) { 02629 if (t->e2->triangles->data != t) 02630 traverse_manifold (t->e2->triangles->data, s); 02631 else 02632 traverse_manifold (t->e2->triangles->next->data, s); 02633 } 02634 if (g_slist_length (t->e3->triangles) == 2) { 02635 if (t->e3->triangles->data != t) 02636 traverse_manifold (t->e3->triangles->data, s); 02637 else 02638 traverse_manifold (t->e3->triangles->next->data, s); 02639 } 02640 } 02641 02642 static void non_manifold_edges (GtsEdge * e, gpointer * data) 02643 { 02644 GtsSurface * s = data[0]; 02645 GSList ** non_manifold = data[1]; 02646 02647 if (gts_edge_face_number (e, s) > 2) { 02648 GSList * i = e->triangles; 02649 02650 while (i) { 02651 if (gts_face_has_parent_surface (i->data, s) && 02652 !g_slist_find (*non_manifold, i->data)) 02653 *non_manifold = g_slist_prepend (*non_manifold, i->data); 02654 i = i->next; 02655 } 02656 } 02657 } 02658 02659 static void traverse_boundary (GtsEdge * e, gpointer * data) 02660 { 02661 GtsSurface * orig = data[0]; 02662 GSList ** components = data[1]; 02663 GtsFace * f = gts_edge_is_boundary (e, orig); 02664 02665 if (f != NULL && g_slist_length (f->surfaces) == 1) { 02666 GtsSurface * s = 02667 gts_surface_new (GTS_SURFACE_CLASS (GTS_OBJECT (orig)->klass), 02668 orig->face_class, 02669 orig->edge_class, 02670 orig->vertex_class); 02671 GSList * non_manifold = NULL, * i; 02672 gpointer data[2]; 02673 02674 *components = g_slist_prepend (*components, s); 02675 data[0] = s; 02676 data[1] = &non_manifold; 02677 traverse_manifold (GTS_TRIANGLE (f), s); 02678 02679 gts_surface_foreach_edge (s, (GtsFunc) non_manifold_edges, data); 02680 i = non_manifold; 02681 while (i) { 02682 gts_surface_remove_face (s, i->data); 02683 i = i->next; 02684 } 02685 g_slist_free (non_manifold); 02686 } 02687 } 02688 02689 static void traverse_remaining (GtsFace * f, gpointer * data) 02690 { 02691 GtsSurface * orig = data[0]; 02692 GSList ** components = data[1]; 02693 02694 if (g_slist_length (f->surfaces) == 1) { 02695 GtsSurface * s = 02696 gts_surface_new (GTS_SURFACE_CLASS (GTS_OBJECT (orig)->klass), 02697 orig->face_class, 02698 orig->edge_class, 02699 orig->vertex_class); 02700 GSList * non_manifold = NULL, * i; 02701 gpointer data[2]; 02702 02703 *components = g_slist_prepend (*components, s); 02704 data[0] = s; 02705 data[1] = &non_manifold; 02706 traverse_manifold (GTS_TRIANGLE (f), s); 02707 02708 gts_surface_foreach_edge (s, (GtsFunc) non_manifold_edges, data); 02709 i = non_manifold; 02710 while (i) { 02711 gts_surface_remove_face (s, i->data); 02712 i = i->next; 02713 } 02714 g_slist_free (non_manifold); 02715 } 02716 } 02717 02726 GSList * gts_surface_split (GtsSurface * s) 02727 { 02728 gpointer data[2]; 02729 GSList * components = NULL; 02730 02731 g_return_val_if_fail (s != NULL, NULL); 02732 02733 data[0] = s; 02734 data[1] = &components; 02735 02736 /* boundary components */ 02737 gts_surface_foreach_edge (s, (GtsFunc) traverse_boundary, data); 02738 02739 /* remaining components */ 02740 gts_surface_foreach_face (s, (GtsFunc) traverse_remaining, data); 02741 02742 return components; 02743 }