Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

tubes.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 McConnell Brain Imaging Centre, 00005 Montreal Neurological Institute, McGill University. 00006 Permission to use, copy, modify, and distribute this 00007 software and its documentation for any purpose and without 00008 fee is hereby granted, provided that the above copyright 00009 notice appear in all copies. The author and McGill University 00010 make no representations about the suitability of this 00011 software for any purpose. It is provided "as is" without 00012 express or implied warranty. 00013 ---------------------------------------------------------------------------- */ 00014 00015 #include <volume_io/internal_volume_io.h> 00016 #include <bicpl/geom.h> 00017 00018 #ifndef lint 00019 static char rcsid[] = "$Header: /software/source//libraries/bicpl/Geometry/tubes.c,v 1.6 2000/02/06 15:30:20 stever Exp $"; 00020 #endif 00021 00022 private void generate_tube( 00023 int n_points, 00024 Point points[], 00025 int n_around, 00026 Real radius, 00027 Point tube_points[], 00028 Vector tube_normals[] ); 00029 00030 /* ----------------------------- MNI Header ----------------------------------- 00031 @NAME : create_tube 00032 @INPUT : n_points 00033 points 00034 n_around 00035 radius 00036 colour 00037 @OUTPUT : quadmesh 00038 @RETURNS : 00039 @DESCRIPTION: Creates a quadmesh cylindrical tube corresponding to the points. 00040 @METHOD : 00041 @GLOBALS : 00042 @CALLS : 00043 @CREATED : 1993 David MacDonald 00044 @MODIFIED : 00045 ---------------------------------------------------------------------------- */ 00046 00047 private void create_tube( 00048 int n_points, 00049 Point points[], 00050 int n_around, 00051 Real radius, 00052 Colour colour, 00053 quadmesh_struct *quadmesh ) 00054 { 00055 Surfprop spr; 00056 00057 get_default_surfprop( &spr ); 00058 00059 initialize_quadmesh( quadmesh, colour, &spr, n_points, n_around ); 00060 quadmesh->m_closed = FALSE; 00061 quadmesh->n_closed = TRUE; 00062 00063 generate_tube( n_points, points, n_around, radius, 00064 quadmesh->points, quadmesh->normals ); 00065 } 00066 00067 /* ----------------------------- MNI Header ----------------------------------- 00068 @NAME : convert_lines_to_tubes 00069 @INPUT : lines 00070 n_around 00071 radius 00072 @OUTPUT : quadmeshes 00073 @RETURNS : number of quadmeshes 00074 @DESCRIPTION: Creates a set of quadmeshes representing tubes corresponding 00075 to the lines structure, returning the number of quadmeshes 00076 (the number of separate lines). 00077 @METHOD : 00078 @GLOBALS : 00079 @CALLS : 00080 @CREATED : 1993 David MacDonald 00081 @MODIFIED : 00082 ---------------------------------------------------------------------------- */ 00083 00084 public int convert_lines_to_tubes( 00085 lines_struct *lines, 00086 int n_around, 00087 Real radius, 00088 quadmesh_struct *quadmeshes[] ) 00089 { 00090 int i, l, line_size; 00091 quadmesh_struct *quadmesh; 00092 Point *points; 00093 00094 if( lines->n_items == 0 ) 00095 return( 0 ); 00096 00097 ALLOC( *quadmeshes, lines->n_items ); 00098 00099 for_less( l, 0, lines->n_items ) 00100 { 00101 line_size = GET_OBJECT_SIZE( *lines, l ); 00102 00103 ALLOC( points, line_size ); 00104 00105 for_less( i, 0, line_size ) 00106 { 00107 points[i] = lines->points[lines->indices[ 00108 POINT_INDEX(lines->end_indices,l,i)]]; 00109 } 00110 00111 quadmesh = &(*quadmeshes)[l]; 00112 00113 create_tube( line_size, points, n_around, radius, lines->colours[0], 00114 quadmesh ); 00115 00116 FREE( points ); 00117 } 00118 00119 return( lines->n_items ); 00120 } 00121 00122 /* ----------------------------- MNI Header ----------------------------------- 00123 @NAME : get_direction 00124 @INPUT : n_points 00125 points 00126 i 00127 wrap_around 00128 @OUTPUT : dir 00129 @RETURNS : 00130 @DESCRIPTION: Gets the direction of the line segment from i to i+1 of the 00131 points, with or without wraparound. 00132 @METHOD : 00133 @GLOBALS : 00134 @CALLS : 00135 @CREATED : 1993 David MacDonald 00136 @MODIFIED : 00137 ---------------------------------------------------------------------------- */ 00138 00139 private void get_direction( 00140 int n_points, 00141 Point points[], 00142 int i, 00143 BOOLEAN wrap_around, 00144 Vector *dir ) 00145 { 00146 int end; 00147 00148 end = i; 00149 00150 do 00151 { 00152 ++end; 00153 if( end == n_points && wrap_around ) 00154 end = 0; 00155 } 00156 while( end < n_points && end != i && EQUAL_POINTS(points[i],points[end]) ); 00157 00158 if( end >= n_points || end == i ) 00159 { 00160 fill_Vector( *dir, 0.0, 0.0, 0.0 ); 00161 } 00162 else 00163 { 00164 SUB_POINTS( *dir, points[end], points[i] ); 00165 00166 NORMALIZE_VECTOR( *dir, *dir ); 00167 } 00168 } 00169 00170 /* ----------------------------- MNI Header ----------------------------------- 00171 @NAME : fill_in_ellipse_points 00172 @INPUT : centre 00173 n_around 00174 x 00175 y 00176 hor 00177 vert 00178 @OUTPUT : tube_points 00179 tube_normals 00180 @RETURNS : 00181 @DESCRIPTION: Given x,y positions in 2D space and a horizontal and vertical 00182 vector, fills in the 3D ellipse points into the tube points 00183 and normals 00184 @METHOD : 00185 @GLOBALS : 00186 @CALLS : 00187 @CREATED : 1993 David MacDonald 00188 @MODIFIED : 00189 ---------------------------------------------------------------------------- */ 00190 00191 private void fill_in_ellipse_points( 00192 Point tube_points[], 00193 Vector tube_normals[], 00194 Point *centre, 00195 int n_around, 00196 Real x[], 00197 Real y[], 00198 Vector *hor, 00199 Vector *vert ) 00200 { 00201 int i; 00202 Vector h, v, offset; 00203 00204 for_less( i, 0, n_around ) 00205 { 00206 SCALE_VECTOR( h, *hor, x[i] ); 00207 SCALE_VECTOR( v, *vert, y[i] ); 00208 00209 ADD_VECTORS( offset, h, v ); 00210 00211 ADD_POINT_VECTOR( tube_points[i], *centre, offset ); 00212 NORMALIZE_VECTOR( tube_normals[i], offset ); 00213 } 00214 } 00215 00216 /* ----------------------------- MNI Header ----------------------------------- 00217 @NAME : project_vector_to_plane 00218 @INPUT : v 00219 direction 00220 normal 00221 @OUTPUT : projected 00222 @RETURNS : 00223 @DESCRIPTION: Projects a vector onto a plane, along the direction. Finds the 00224 point on the line through v in the direction direction, which 00225 is on the plane perpendicular to normal. Solves the equation 00226 (V + t * Direction) dot Normal = 0 00227 @METHOD : 00228 @GLOBALS : 00229 @CALLS : 00230 @CREATED : 1993 David MacDonald 00231 @MODIFIED : 00232 ---------------------------------------------------------------------------- */ 00233 00234 private void project_vector_to_plane( 00235 Vector *v, 00236 Vector *direction, 00237 Vector *normal, 00238 Vector *projected ) 00239 { 00240 Vector offset; 00241 Real t, n_dot_d, n_dot_v; 00242 00243 n_dot_d = DOT_VECTORS( *normal, *direction ); 00244 00245 if( n_dot_d == 0.0 ) 00246 { 00247 print_error( "Error in project_vector_to_plane\n" ); 00248 } 00249 else 00250 { 00251 n_dot_v = DOT_VECTORS( *normal, *v ); 00252 00253 t = - n_dot_v / n_dot_d; 00254 00255 SCALE_VECTOR( offset, *direction, t ); 00256 ADD_VECTORS( *projected, *v, offset ); 00257 } 00258 } 00259 00260 /* ----------------------------- MNI Header ----------------------------------- 00261 @NAME : generate_tube 00262 @INPUT : n_points 00263 points 00264 n_around 00265 radius 00266 @OUTPUT : tube_points 00267 tube_normals 00268 @RETURNS : 00269 @DESCRIPTION: Generates a tube quadmesh from a set of points. 00270 @METHOD : 00271 @GLOBALS : 00272 @CALLS : 00273 @CREATED : 1993 David MacDonald 00274 @MODIFIED : 00275 ---------------------------------------------------------------------------- */ 00276 00277 private void generate_tube( 00278 int n_points, 00279 Point points[], 00280 int n_around, 00281 Real radius, 00282 Point tube_points[], 00283 Vector tube_normals[] ) 00284 { 00285 int i; 00286 Real *x, *y, angle; 00287 Vector hor, vert, dir, prev_dir, normal; 00288 BOOLEAN wrap_around; 00289 00290 ALLOC( x, n_around ); 00291 ALLOC( y, n_around ); 00292 00293 for_less( i, 0, n_around ) 00294 { 00295 angle = (Real) (n_around - 1 - i) / (Real) n_around * 2.0 * PI; 00296 x[i] = radius * cos( angle ); 00297 y[i] = radius * sin( angle ); 00298 } 00299 00300 wrap_around = EQUAL_POINTS( points[0], points[n_points-1] ); 00301 00302 get_direction( n_points, points, 0, wrap_around, &dir ); 00303 create_orthogonal_vector( &dir, &hor ); 00304 00305 if( wrap_around ) 00306 get_direction( n_points, points, n_points-2, wrap_around, &prev_dir ); 00307 else 00308 prev_dir = dir; 00309 00310 for_less( i, 0, n_points ) 00311 { 00312 CROSS_VECTORS( vert, prev_dir, hor ); 00313 NORMALIZE_VECTOR( vert, vert ); 00314 00315 CROSS_VECTORS( hor, vert, prev_dir ); 00316 NORMALIZE_VECTOR( hor, hor ); 00317 00318 ADD_VECTORS( normal, prev_dir, dir ); 00319 NORMALIZE_VECTOR( normal, normal ); 00320 00321 project_vector_to_plane( &hor, &prev_dir, &normal, &hor ); 00322 project_vector_to_plane( &vert, &prev_dir, &normal, &vert ); 00323 00324 fill_in_ellipse_points( &tube_points[IJ(i,0,n_around)], 00325 &tube_normals[IJ(i,0,n_around)], 00326 &points[i], n_around, x, y, &hor, &vert ); 00327 00328 if( i < n_points-1 ) 00329 { 00330 prev_dir = dir; 00331 00332 if( wrap_around || i < n_points-2 ) 00333 get_direction( n_points, points, i+1, wrap_around, &dir ); 00334 } 00335 } 00336 00337 FREE( x ); 00338 FREE( y ); 00339 }

Generated on Wed Jul 28 09:10:58 2004 for BICPL by doxygen 1.3.7