00001
#include <volume_io/internal_volume_io.h>
00002
#include <bicpl/geom.h>
00003
00004 #define STATIC_STORAGE 1000
00005
00006 public int clip_polygon_against_box(
00007
int n_points,
00008 Point points[],
00009 Real x_min,
00010 Real x_max,
00011 Real y_min,
00012 Real y_max,
00013 Real z_min,
00014 Real z_max,
00015
int n_output_points,
00016 Point output_points[] )
00017 {
00018
int p, n_planes, n_out, n, i;
00019
int n_input[7], dim, which;
00020 BOOLEAN last[7][2], first_flags[6], last_flag;
00021 Point prev[6], input[7][2], point, first_points[6];
00022 Real box[2][N_DIMENSIONS], prev_dist[6], first_dist[6], dist, ratio;
00023
00024 box[0][X] = x_min;
00025 box[1][X] = x_max;
00026 box[0][Y] = y_min;
00027 box[1][Y] = y_max;
00028 box[0][Z] = z_min;
00029 box[1][Z] = z_max;
00030 n_planes = 6;
00031
00032 for_less( p, 0, n_planes )
00033 {
00034 first_flags[p] =
TRUE;
00035 n_input[p] = 0;
00036 }
00037 n_input[n_planes] = 0;
00038
00039 n_out = 0;
00040
00041 for_less( i, 0, n_points+1 )
00042 {
00043 input[0][0] = points[i%n_points];
00044 last[0][0] = (i == n_points);
00045 n_input[0] = 1;
00046 p = 0;
00047
00048
while( p >= 0 )
00049 {
00050 --n_input[p];
00051 point = input[p][n_input[p]];
00052 last_flag = last[p][n_input[p]];
00053
00054
if( !last_flag )
00055 {
00056 dim = p / 2;
00057 which = p % 2;
00058
if( which == 0 )
00059 dist = RPoint_coord(point,dim) - box[0][dim];
00060
else
00061 dist = box[1][dim] - RPoint_coord(point,dim);
00062
00063
if( dist >= 0.0 )
00064 {
00065 input[p+1][0] = point;
00066 last[p+1][0] =
FALSE;
00067 n_input[p+1] = 1;
00068 }
00069 }
00070
else
00071 {
00072 dist = first_dist[p];
00073 point = first_points[p];
00074
00075
if( !first_flags[p] && p < n_planes - 1 )
00076 {
00077 last[p+1][0] =
TRUE;
00078 n_input[p+1] = 1;
00079 }
00080 }
00081
00082
if( first_flags[p] )
00083 {
00084 first_points[p] = point;
00085 first_flags[p] =
FALSE;
00086 first_dist[p] = dist;
00087 }
00088
else if( prev_dist[p] * dist < 0.0 )
00089 {
00090 ratio = prev_dist[p] / (prev_dist[p] - dist);
00091 n = n_input[p+1];
00092 INTERPOLATE_POINTS( input[p+1][n], prev[p], point, ratio );
00093 last[p+1][n] =
FALSE;
00094 ++n_input[p+1];
00095 }
00096
00097 prev[p] = point;
00098 prev_dist[p] = dist;
00099
00100 ++p;
00101
00102
if( p == n_planes && n_input[p] > 0 )
00103 {
00104 n = n_input[p];
00105 for_down( n, n_input[p]-1, 0 )
00106 {
00107
if ( n_out >= n_output_points )
00108 {
00109 handle_internal_error(
"too many points generated in clip_polygon_against_box()" );
00110
return( n_out );
00111 }
00112 output_points[n_out] = input[p][n];
00113 ++n_out;
00114 }
00115 n_input[p] = 0;
00116 --p;
00117 }
00118
00119
while( p >= 0 && n_input[p] == 0 )
00120 --p;
00121 }
00122 }
00123
00124
return( n_out );
00125 }
00126
00127 public int clip_polygon_against_plane(
00128
int n_points,
00129 Point points[],
00130 Real plane_constant,
00131 Vector *normal,
00132 Point output_points[] )
00133 {
00134
int p, n_output;
00135 Real next_dist, dist, ratio;
00136 Point point, next_point;
00137
00138 n_output = 0;
00139 dist = 0.0;
00140
00141 next_dist = DOT_POINT_VECTOR( *normal, points[0] ) + plane_constant;
00142 next_point = points[0];
00143
00144 for_less( p, 0, n_points )
00145 {
00146 dist = next_dist;
00147 point = next_point;
00148 next_point = points[(p+1) % n_points];
00149 next_dist = DOT_POINT_VECTOR( *normal, next_point ) + plane_constant;
00150
00151
if( dist >= 0.0 )
00152 {
00153 output_points[n_output] = point;
00154 ++n_output;
00155 }
00156
00157
if( (n_points > 2 || (p == 0 && n_points == 2))
00158 && dist * next_dist < 0.0 )
00159 {
00160 ratio = dist / (dist - next_dist);
00161 INTERPOLATE_POINTS( output_points[n_output],
00162 point, next_point, ratio );
00163 ++n_output;
00164 }
00165 }
00166
00167
return( n_output );
00168 }
00169
00170 public void split_polygon_with_plane(
00171
int n_points,
00172 Point points[],
00173 Real plane_constant,
00174 Vector *normal,
00175
int *n_in,
00176 Point in_points[],
00177
int *n_out,
00178 Point out_points[] )
00179 {
00180
int p;
00181 Real next_dist, dist, ratio;
00182 Point point, next_point, interp;
00183
00184 *n_in = 0;
00185 *n_out = 0;
00186 dist = 0.0;
00187
00188 next_dist = DOT_POINT_VECTOR( *normal, points[0] ) + plane_constant;
00189 next_point = points[0];
00190
00191 for_less( p, 0, n_points )
00192 {
00193 dist = next_dist;
00194 point = next_point;
00195 next_point = points[(p+1) % n_points];
00196 next_dist = DOT_POINT_VECTOR( *normal, next_point ) + plane_constant;
00197
00198
if( dist >= 0.0 )
00199 {
00200 in_points[*n_in] = point;
00201 ++(*n_in);
00202 }
00203
00204
if( dist <= 0.0 )
00205 {
00206 out_points[*n_out] = point;
00207 ++(*n_out);
00208 }
00209
00210
if( (n_points > 2 || (p == 0 && n_points == 2))
00211 && dist * next_dist < 0.0 )
00212 {
00213 ratio = dist / (dist - next_dist);
00214 INTERPOLATE_POINTS( interp, point, next_point, ratio );
00215 in_points[*n_in] = interp;
00216 ++(*n_in);
00217 out_points[*n_out] = interp;
00218 ++(*n_out);
00219 }
00220 }
00221 }