/** * gts_bbox_points: * @klass: a #GtsBBoxClass. * @points: a list of #GtsPoint. * * Returns: a new #GtsBBox bounding box of @points. */ GtsBBox * gts_bbox_points (GtsBBoxClass * klass, GSList * points) { GtsPoint * p; GtsBBox * bbox; GSList * i; if (points == NULL) return NULL; p = points->data; bbox = gts_bbox_new (klass, points, p->x, p->y, p->z, p->x, p->y, p->z); i = points->next; while (i) { p = i->data; if (p->x > bbox->x2) bbox->x2 = p->x; else if (p->x < bbox->x1) bbox->x1 = p->x; if (p->y > bbox->y2) bbox->y2 = p->y; else if (p->y < bbox->y1) bbox->y1 = p->y; if (p->z > bbox->z2) bbox->z2 = p->z; else if (p->z < bbox->z1) bbox->z1 = p->z; i = i->next; } return bbox; }
/** * gts_bbox_bboxes: * @klass: a #GtsBBoxClass. * @bboxes: a list of #GtsBBox. * * Returns: a new #GtsBBox bounding box of all the bounding boxes in * @bboxes. */ GtsBBox * gts_bbox_bboxes (GtsBBoxClass * klass, GSList * bboxes) { GtsBBox * bbox; GtsBBox * bb; g_return_val_if_fail (bboxes != NULL, NULL); g_return_val_if_fail (klass != NULL, NULL); bb = bboxes->data; bbox = gts_bbox_new (klass, bboxes, bb->x1, bb->y1, bb->z1, bb->x2, bb->y2, bb->z2); bboxes = bboxes->next; while (bboxes) { bb = bboxes->data; if (bb->x1 < bbox->x1) bbox->x1 = bb->x1; if (bb->y1 < bbox->y1) bbox->y1 = bb->y1; if (bb->z1 < bbox->z1) bbox->z1 = bb->z1; if (bb->x2 > bbox->x2) bbox->x2 = bb->x2; if (bb->y2 > bbox->y2) bbox->y2 = bb->y2; if (bb->z2 > bbox->z2) bbox->z2 = bb->z2; bboxes = bboxes->next; } return bbox; }
/** * gts_bbox_segment: * @klass: a #GtsBBoxClass. * @s: a #GtsSegment. * * Returns: a new #GtsBBox bounding box of @s. */ GtsBBox * gts_bbox_segment (GtsBBoxClass * klass, GtsSegment * s) { GtsBBox * bbox; GtsPoint * p1, * p2; g_return_val_if_fail (s != NULL, NULL); g_return_val_if_fail (klass != NULL, NULL); bbox = gts_bbox_new (klass, s, 0., 0., 0., 0., 0., 0.); p1 = GTS_POINT (s->v1); p2 = GTS_POINT (s->v2); if (p1->x > p2->x) { bbox->x2 = p1->x; bbox->x1 = p2->x; } else { bbox->x1 = p1->x; bbox->x2 = p2->x; } if (p1->y > p2->y) { bbox->y2 = p1->y; bbox->y1 = p2->y; } else { bbox->y1 = p1->y; bbox->y2 = p2->y; } if (p1->z > p2->z) { bbox->z2 = p1->z; bbox->z1 = p2->z; } else { bbox->z1 = p1->z; bbox->z2 = p2->z; } return bbox; }
/** * gts_bbox_triangle: * @klass: a #GtsBBoxClass. * @t: a #GtsTriangle. * * Returns: a new #GtsBBox bounding box of @t. */ GtsBBox * gts_bbox_triangle (GtsBBoxClass * klass, GtsTriangle * t) { GtsBBox * bbox; GtsPoint * p; g_return_val_if_fail (t != NULL, NULL); g_return_val_if_fail (klass != NULL, NULL); p = GTS_POINT (GTS_SEGMENT (t->e1)->v1); bbox = gts_bbox_new (klass, t, p->x, p->y, p->z, p->x, p->y, p->z); p = GTS_POINT (GTS_SEGMENT (t->e1)->v2); if (p->x > bbox->x2) bbox->x2 = p->x; if (p->x < bbox->x1) bbox->x1 = p->x; if (p->y > bbox->y2) bbox->y2 = p->y; if (p->y < bbox->y1) bbox->y1 = p->y; if (p->z > bbox->z2) bbox->z2 = p->z; if (p->z < bbox->z1) bbox->z1 = p->z; p = GTS_POINT (gts_triangle_vertex (t)); if (p->x > bbox->x2) bbox->x2 = p->x; if (p->x < bbox->x1) bbox->x1 = p->x; if (p->y > bbox->y2) bbox->y2 = p->y; if (p->y < bbox->y1) bbox->y1 = p->y; if (p->z > bbox->z2) bbox->z2 = p->z; if (p->z < bbox->z1) bbox->z1 = p->z; return bbox; }
int main (int argc, char * argv[]) { GtsSurface * s; GtsBBox * bbox; gdouble delta; GtsPoint * p1, * p2, * p3; guint nt; GtsRange cluster_stats; GtsClusterGrid * cluster_grid; if (argc != 2) { fprintf (stderr, "usage: oocs DELTA < infile > outfile\n"); return 1; } s = gts_surface_new (gts_surface_class (), gts_face_class (), gts_edge_class (), gts_vertex_class ()); bbox = gts_bbox_new (gts_bbox_class (), s, 0., 0., 0., 0., 0., 0.); scanf ("%u", &nt); scanf ("%lf %lf %lf", &bbox->x1, &bbox->y1, &bbox->z1); scanf ("%lf %lf %lf", &bbox->x2, &bbox->y2, &bbox->z2); delta = atof (argv[1])*sqrt (gts_bbox_diagonal2 (bbox)); cluster_grid = gts_cluster_grid_new (gts_cluster_grid_class (), gts_cluster_class (), s, bbox, delta); p1 = gts_point_new (gts_point_class (), 0., 0., 0.); p2 = gts_point_new (gts_point_class (), 0., 0., 0.); p3 = gts_point_new (gts_point_class (), 0., 0., 0.); while (scanf ("%lf %lf %lf", &p1->x, &p1->y, &p1->z) == 3 && scanf ("%lf %lf %lf", &p2->x, &p2->y, &p2->z) == 3 && scanf ("%lf %lf %lf", &p3->x, &p3->y, &p3->z) == 3) gts_cluster_grid_add_triangle (cluster_grid, p1, p2, p3, NULL); cluster_stats = gts_cluster_grid_update (cluster_grid); gts_object_destroy (GTS_OBJECT (p1)); gts_object_destroy (GTS_OBJECT (p2)); gts_object_destroy (GTS_OBJECT (p3)); gts_object_destroy (GTS_OBJECT (cluster_grid)); fprintf (stderr, "Initial number of triangles: %u\n", nt); fprintf (stderr, "%d clusters of size: min: %g avg: %.1f|%.1f max: %g\n", cluster_stats.n, cluster_stats.min, cluster_stats.mean, cluster_stats.stddev, cluster_stats.max); gts_surface_print_stats (s, stderr); gts_surface_write (s, stdout); return 0; }
/** * gts_bbox_surface: * @klass: a #GtsBBoxClass. * @surface: a #GtsSurface. * * Returns: a new #GtsBBox bounding box of @surface. */ GtsBBox * gts_bbox_surface (GtsBBoxClass * klass, GtsSurface * surface) { GtsBBox * bbox; g_return_val_if_fail (klass != NULL, NULL); g_return_val_if_fail (surface != NULL, NULL); bbox = gts_bbox_new (klass, surface, 0., 0., 0., 0., 0., 0.); bbox->x1 = bbox->y1 = bbox->z1 = G_MAXDOUBLE; bbox->x2 = bbox->y2 = bbox->z2 = -G_MAXDOUBLE; gts_surface_foreach_vertex (surface, (GtsFunc) bbox_foreach_vertex, bbox); return bbox; }
/* This function is modified from the original in GTS in order to avoid * deallocating any objects referenced by the live-objects table. The * approach is similar to what is used for replace() in vertex.c. */ GList* pygts_vertices_merge(GList* vertices, gdouble epsilon, gboolean (* check) (GtsVertex *, GtsVertex *)) { GPtrArray *array; GList *i, *next; GNode *kdtree; GtsVertex *v; GtsBBox *bbox; GSList *selected, *j; GtsVertex *sv; PygtsObject *obj; PygtsVertex *vertex=NULL; GSList *parents=NULL, *ii,*cur; g_return_val_if_fail(vertices != NULL, 0); array = g_ptr_array_new(); i = vertices; while (i) { g_ptr_array_add(array, i->data); i = g_list_next(i); } kdtree = gts_kdtree_new(array, NULL); g_ptr_array_free(array, TRUE); i = vertices; while(i) { v = (GtsVertex*)i->data; if (!GTS_OBJECT(v)->reserved) { /* Do something only if v is active */ /* build bounding box */ bbox = gts_bbox_new(gts_bbox_class(), v, GTS_POINT(v)->x - epsilon, GTS_POINT(v)->y - epsilon, GTS_POINT(v)->z - epsilon, GTS_POINT(v)->x + epsilon, GTS_POINT(v)->y + epsilon, GTS_POINT(v)->z + epsilon); /* select vertices which are inside bbox using kdtree */ j = selected = gts_kdtree_range(kdtree, bbox, NULL); while(j) { sv = (GtsVertex*)j->data; if( sv!=v && !GTS_OBJECT(sv)->reserved && (!check||(*check)(sv, v)) ) { /* sv is not v and is active */ if( (obj = (PygtsObject*)g_hash_table_lookup(obj_table,GTS_OBJECT(sv))) !=NULL ) { vertex = PYGTS_VERTEX(obj); /* Detach and save any parent segments */ ii = sv->segments; while(ii!=NULL) { cur = ii; ii = g_slist_next(ii); if(PYGTS_IS_PARENT_SEGMENT(cur->data)) { sv->segments = g_slist_remove_link(sv->segments, cur); parents = g_slist_prepend(parents,cur->data); g_slist_free_1(cur); } } } gts_vertex_replace(sv, v); GTS_OBJECT(sv)->reserved = sv; /* mark sv as inactive */ /* Reattach the parent segments */ if( vertex != NULL ) { ii = parents; while(ii!=NULL) { sv->segments = g_slist_prepend(sv->segments, ii->data); ii = g_slist_next(ii); } g_slist_free(parents); parents = NULL; } vertex = NULL; } j = g_slist_next(j); } g_slist_free(selected); gts_object_destroy(GTS_OBJECT(bbox)); } i = g_list_next(i); } gts_kdtree_destroy(kdtree); /* destroy inactive vertices and removes them from list */ /* we want to control vertex destruction */ gts_allow_floating_vertices = TRUE; i = vertices; while (i) { v = (GtsVertex*)i->data; next = g_list_next(i); if(GTS_OBJECT(v)->reserved) { /* v is inactive */ if( g_hash_table_lookup(obj_table,GTS_OBJECT(v))==NULL ) { gts_object_destroy(GTS_OBJECT(v)); } else { GTS_OBJECT(v)->reserved = 0; } vertices = g_list_remove_link(vertices, i); g_list_free_1(i); } i = next; } gts_allow_floating_vertices = FALSE; return vertices; }