00001
#include <volume_io/internal_volume_io.h>
00002
#include <bicpl/objects.h>
00003
#include <bicpl/geom.h>
00004
00005 #define N_BOX_RATIO 0.05
00006 #define MIN_N_BOXES 10
00007
00008 typedef struct
00009
{
00010 int n_points;
00011 int *point_indices;
00012 }
box_struct;
00013
00014 private void get_box_index(
00015 Point *point,
00016 Point *min_point,
00017 Point *max_point,
00018
int n_boxes[],
00019
int *i,
00020
int *j,
00021
int *k )
00022 {
00023 Real diff, p, min_p, max_p;
00024
int dim, *coords[N_DIMENSIONS];
00025
00026 coords[X] = i;
00027 coords[Y] = j;
00028 coords[Z] = k;
00029
00030 for_less( dim, 0, N_DIMENSIONS )
00031 {
00032 p = (Real) Point_coord(*point,dim);
00033 min_p = (Real) Point_coord(*min_point,dim);
00034 max_p = (Real) Point_coord(*max_point,dim);
00035
if( p <= min_p )
00036 *(coords[dim]) = 0;
00037
else if( p >= max_p )
00038 *(coords[dim]) = n_boxes[dim]-1;
00039
else
00040 {
00041 diff = max_p - min_p;
00042
if( diff <= 0.0 )
00043 *(coords[dim]) = 0;
00044
else
00045 *(coords[dim]) = (
int) ((Real) n_boxes[dim] *
00046 (p - min_p) / diff);
00047 }
00048 }
00049 }
00050
00051 public void coalesce_object_points(
00052
int *n_points,
00053 Point *points[],
00054
int n_indices,
00055
int indices[] )
00056 {
00057
int n_boxes[N_DIMENSIONS];
00058
int i, j, k, p, point, ind, *points_list, *translation;
00059
int cum_index, dim, new_n_points;
00060
box_struct ***boxes;
00061 Point min_point, max_point, *new_points;
00062
00063 new_points = NULL;
00064
00065
get_range_points( *n_points, *points, &min_point, &max_point );
00066
00067 for_less( dim, 0, N_DIMENSIONS )
00068 {
00069 n_boxes[dim] = (
int) pow( (Real) *n_points *
N_BOX_RATIO, 0.3333 );
00070
if( n_boxes[dim] <
MIN_N_BOXES )
00071 n_boxes[dim] =
MIN_N_BOXES;
00072
if( Point_coord(min_point,dim) == Point_coord(max_point,dim) )
00073 n_boxes[dim] = 1;
00074 }
00075
00076 ALLOC3D( boxes, n_boxes[X], n_boxes[Y], n_boxes[Z] );
00077
00078 for_less( i, 0, n_boxes[X] )
00079 for_less( j, 0, n_boxes[Y] )
00080 for_less( k, 0, n_boxes[Z] )
00081 {
00082 boxes[i][j][k].
n_points = 0;
00083 }
00084
00085 for_less( point, 0, *n_points )
00086 {
00087
get_box_index( &(*points)[point], &min_point, &max_point, n_boxes,
00088 &i, &j, &k );
00089 ++boxes[i][j][k].
n_points;
00090 }
00091
00092 ALLOC( points_list, *n_points );
00093
00094 cum_index = 0;
00095 for_less( i, 0, n_boxes[X] )
00096 for_less( j, 0, n_boxes[Y] )
00097 for_less( k, 0, n_boxes[Z] )
00098 {
00099 boxes[i][j][k].
point_indices = &points_list[cum_index];
00100 cum_index += boxes[i][j][k].
n_points;
00101 boxes[i][j][k].n_points = 0;
00102 }
00103
00104 for_less( point, 0, *n_points )
00105 {
00106
get_box_index( &(*points)[point], &min_point, &max_point, n_boxes,
00107 &i, &j, &k );
00108 boxes[i][j][k].
point_indices[boxes[i][j][k].
n_points] = point;
00109 ++boxes[i][j][k].
n_points;
00110 }
00111
00112 ALLOC( translation, *n_points );
00113 for_less( point, 0, *n_points )
00114 translation[point] = -1;
00115
00116 new_n_points = 0;
00117
00118 for_less( point, 0, *n_points )
00119 {
00120
get_box_index( &(*points)[point], &min_point, &max_point, n_boxes,
00121 &i, &j, &k );
00122
00123 for_less( p, 0, boxes[i][j][k].n_points )
00124 {
00125 ind = boxes[i][j][k].
point_indices[p];
00126
if( ind < point && EQUAL_POINTS( (*points)[point], (*points)[ind] ))
00127 {
00128
break;
00129 }
00130 }
00131
00132
if( p < boxes[i][j][k].
n_points )
00133 translation[point] = translation[ind];
00134
else
00135 {
00136 translation[point] = new_n_points;
00137 ADD_ELEMENT_TO_ARRAY( new_points, new_n_points, (*points)[point],
00138 DEFAULT_CHUNK_SIZE );
00139 }
00140 }
00141
00142 for_less( i, 0, n_indices )
00143 indices[i] = translation[indices[i]];
00144
00145 FREE3D( boxes );
00146 FREE( points_list );
00147 FREE( translation );
00148
00149 FREE( *points );
00150 *n_points = new_n_points;
00151 *points = new_points;
00152 }
00153
00154 public void separate_object_points(
00155
int *new_n_points,
00156 Point *points[],
00157
int n_indices,
00158
int indices[],
00159 Colour_flags colour_flag,
00160 Colour *colours[] )
00161 {
00162
int point_index, ind;
00163 Point *new_points;
00164 Colour *new_colours;
00165
00166 new_colours = NULL;
00167 new_points = NULL;
00168 *new_n_points = 0;
00169 for_less( ind, 0, n_indices )
00170 {
00171 point_index = indices[ind];
00172 ADD_ELEMENT_TO_ARRAY( new_points, *new_n_points,
00173 (*points)[point_index], DEFAULT_CHUNK_SIZE );
00174
00175
if( colour_flag ==
PER_VERTEX_COLOURS )
00176 {
00177 --(*new_n_points);
00178 ADD_ELEMENT_TO_ARRAY( new_colours, *new_n_points,
00179 (*colours)[point_index], DEFAULT_CHUNK_SIZE );
00180 }
00181
00182 indices[ind] = *new_n_points - 1;
00183 }
00184
00185 FREE( *points );
00186 *points = new_points;
00187
00188
if( colour_flag ==
PER_VERTEX_COLOURS )
00189 {
00190 FREE( *colours );
00191 *colours = new_colours;
00192 }
00193 }