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

closest_point.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/closest_point.c,v 1.9 2000/02/06 15:30:13 stever Exp $"; 00020 #endif 00021 00022 #define MAX_POINTS 300 00023 00024 /* ----------------------------- MNI Header ----------------------------------- 00025 @NAME : get_point_polygon_distance_sq 00026 @INPUT : point 00027 polygons 00028 poly_index 00029 @OUTPUT : object_point 00030 @RETURNS : distance 00031 @DESCRIPTION: Returns the closest distance from the point to the polygon, 00032 and passes back the closest point in the polygon. 00033 @METHOD : 00034 @GLOBALS : 00035 @CALLS : 00036 @CREATED : 1993 David MacDonald 00037 @MODIFIED : 00038 ---------------------------------------------------------------------------- */ 00039 00040 private Real get_point_polygon_distance_sq( 00041 Point *point, 00042 polygons_struct *polygons, 00043 int poly_index, 00044 Point *object_point ) 00045 { 00046 Point points[MAX_POINTS]; 00047 int size; 00048 00049 if( polygons->visibilities == NULL || 00050 polygons->visibilities[poly_index] ) 00051 { 00052 size = get_polygon_points( polygons, poly_index, points ); 00053 00054 return( find_point_polygon_distance_sq( point, size, points, 00055 object_point ) ); 00056 } 00057 else 00058 return( 1.0e60 ); 00059 } 00060 00061 /* ----------------------------- MNI Header ----------------------------------- 00062 @NAME : get_point_quadmesh_distance 00063 @INPUT : point 00064 quadmeshs 00065 obj_index 00066 @OUTPUT : object_point 00067 @RETURNS : distance 00068 @DESCRIPTION: Returns the closest distance from the point to the quadmesh, 00069 and passes back the closest point in the quadmesh. 00070 @METHOD : 00071 @GLOBALS : 00072 @CALLS : 00073 @CREATED : 1993 David MacDonald 00074 @MODIFIED : 00075 ---------------------------------------------------------------------------- */ 00076 00077 private Real get_point_quadmesh_distance_sq( 00078 Point *point, 00079 quadmesh_struct *quadmesh, 00080 int obj_index, 00081 Point *object_point ) 00082 { 00083 Point points[4]; 00084 int i, j, m, n; 00085 00086 get_quadmesh_n_objects( quadmesh, &m, &n ); 00087 00088 i = obj_index / n; 00089 j = obj_index % n; 00090 00091 get_quadmesh_patch( quadmesh, i, j, points ); 00092 00093 return( find_point_polygon_distance_sq( point, 4, points, object_point ) ); 00094 } 00095 00096 /* ----------------------------- MNI Header ----------------------------------- 00097 @NAME : get_line_segment_alpha 00098 @INPUT : point 00099 p1 \ endpoints of segment 00100 p2 / 00101 @OUTPUT : closest_point 00102 alpha 00103 @RETURNS : 00104 @DESCRIPTION: Finds the closest point on the line segment to the 'point', 00105 and the position of the point on the segment, ranging from 00106 0 to 1. 00107 @METHOD : 00108 @GLOBALS : 00109 @CALLS : 00110 @CREATED : 1993 David MacDonald 00111 @MODIFIED : 00112 ---------------------------------------------------------------------------- */ 00113 00114 private void get_line_segment_alpha( 00115 Point *point, 00116 Point *p1, 00117 Point *p2, 00118 Point *closest_point, 00119 Real *alpha ) 00120 { 00121 Vector p2_minus_p1, p_minus_p1; 00122 Real mag; 00123 00124 SUB_VECTORS( p2_minus_p1, *p2, *p1 ); 00125 SUB_VECTORS( p_minus_p1, *point, *p1 ); 00126 00127 mag = DOT_VECTORS( p2_minus_p1, p2_minus_p1 ); 00128 00129 if( mag == 0.0 ) 00130 *alpha = 0.0; 00131 else 00132 *alpha = DOT_VECTORS( p_minus_p1, p2_minus_p1 ) / mag; 00133 00134 if( *alpha <= 0.0 ) 00135 { 00136 *closest_point = *p1; 00137 *alpha = 0.0; 00138 } 00139 else if( *alpha >= 1.0 ) 00140 { 00141 *closest_point = *p2; 00142 *alpha = 1.0; 00143 } 00144 else 00145 { 00146 INTERPOLATE_POINTS( *closest_point, *p1, *p2, *alpha ); 00147 } 00148 } 00149 00150 /* ----------------------------- MNI Header ----------------------------------- 00151 @NAME : get_closest_point_on_line_segment 00152 @INPUT : point 00153 p1 \ endpoints of segment 00154 p2 / 00155 @OUTPUT : closest_point 00156 @RETURNS : 00157 @DESCRIPTION: Finds the closest point on the line segment to the 'point'. 00158 @METHOD : 00159 @GLOBALS : 00160 @CALLS : 00161 @CREATED : 1993 David MacDonald 00162 @MODIFIED : 00163 ---------------------------------------------------------------------------- */ 00164 00165 public void get_closest_point_on_line_segment( 00166 Point *point, 00167 Point *p1, 00168 Point *p2, 00169 Point *closest_point ) 00170 { 00171 Real t; 00172 00173 get_line_segment_alpha( point, p1, p2, closest_point, &t ); 00174 } 00175 00176 /* ----------------------------- MNI Header ----------------------------------- 00177 @NAME : get_distance_to_line_segment 00178 @INPUT : point 00179 p1 \ endpoints of segment 00180 p2 / 00181 @OUTPUT : alpha 00182 @RETURNS : Distance 00183 @DESCRIPTION: Finds the distance to the line segment, and returns the 00184 relative position on the segment of the closest point 00185 @METHOD : 00186 @GLOBALS : 00187 @CALLS : 00188 @CREATED : 1993 David MacDonald 00189 @MODIFIED : 00190 ---------------------------------------------------------------------------- */ 00191 00192 public Real get_distance_to_line_segment( 00193 Point *point, 00194 Point *p1, 00195 Point *p2, 00196 Real *alpha ) 00197 { 00198 Point closest; 00199 00200 get_line_segment_alpha( point, p1, p2, &closest, alpha ); 00201 00202 return( distance_between_points( point, &closest ) ); 00203 } 00204 00205 /* ----------------------------- MNI Header ----------------------------------- 00206 @NAME : get_point_line_segment_distance_sq 00207 @INPUT : point 00208 lines 00209 obj_index 00210 @OUTPUT : object_point 00211 @RETURNS : distance 00212 @DESCRIPTION: Returns the distance to the closest point on the line segment. 00213 @METHOD : 00214 @GLOBALS : 00215 @CALLS : 00216 @CREATED : 1993 David MacDonald 00217 @MODIFIED : 00218 ---------------------------------------------------------------------------- */ 00219 00220 private Real get_point_line_segment_distance_sq( 00221 Point *point, 00222 lines_struct *lines, 00223 int obj_index, 00224 Point *object_point ) 00225 { 00226 int line, seg, p1, p2; 00227 00228 get_line_segment_index( lines, obj_index, &line, &seg ); 00229 00230 p1 = lines->indices[POINT_INDEX(lines->end_indices,line,seg)]; 00231 p2 = lines->indices[POINT_INDEX(lines->end_indices,line,seg+1)]; 00232 00233 get_closest_point_on_line_segment( point, &lines->points[p1], 00234 &lines->points[p2], object_point ); 00235 00236 return( sq_distance_between_points( point, object_point ) ); 00237 } 00238 00239 /* ----------------------------- MNI Header ----------------------------------- 00240 @NAME : get_point_marker_distance 00241 @INPUT : point 00242 marker 00243 @OUTPUT : object_point 00244 @RETURNS : distance 00245 @DESCRIPTION: Returns the distance from the point to the marker. 00246 @METHOD : 00247 @GLOBALS : 00248 @CALLS : 00249 @CREATED : 1993 David MacDonald 00250 @MODIFIED : 00251 ---------------------------------------------------------------------------- */ 00252 00253 private Real get_point_marker_distance( 00254 Point *point, 00255 marker_struct *marker, 00256 Point *object_point ) 00257 { 00258 *object_point = marker->position; 00259 00260 return( distance_between_points( point, object_point ) ); 00261 } 00262 00263 public Real get_point_object_distance_sq( 00264 Point *point, 00265 object_struct *object, 00266 int obj_index, 00267 Point *object_point ) 00268 { 00269 Real dist; 00270 00271 if( get_object_type( object ) == POLYGONS ) 00272 { 00273 dist = get_point_polygon_distance_sq( point, get_polygons_ptr(object), 00274 obj_index, object_point ); 00275 } 00276 else if( get_object_type( object ) == QUADMESH ) 00277 { 00278 dist = get_point_quadmesh_distance_sq( point, get_quadmesh_ptr(object), 00279 obj_index, object_point ); 00280 } 00281 else if( get_object_type( object ) == LINES ) 00282 { 00283 dist = get_point_line_segment_distance_sq( point, get_lines_ptr(object), 00284 obj_index, object_point ); 00285 } 00286 else if( get_object_type( object ) == MARKER ) 00287 { 00288 dist = get_point_marker_distance( point, get_marker_ptr(object), 00289 object_point ); 00290 dist *= dist; 00291 } 00292 else 00293 dist = 1.0e60; 00294 00295 return( dist ); 00296 } 00297 00298 /* ----------------------------- MNI Header ----------------------------------- 00299 @NAME : get_point_object_distance 00300 @INPUT : point 00301 object 00302 obj_index 00303 @OUTPUT : object_point 00304 @RETURNS : distance 00305 @DESCRIPTION: Finds the closest distance to the given object. 00306 @METHOD : 00307 @GLOBALS : 00308 @CALLS : 00309 @CREATED : 1993 David MacDonald 00310 @MODIFIED : 00311 ---------------------------------------------------------------------------- */ 00312 00313 public Real get_point_object_distance( 00314 Point *point, 00315 object_struct *object, 00316 int obj_index, 00317 Point *object_point ) 00318 { 00319 return( sqrt( get_point_object_distance_sq( point, object, 00320 obj_index, object_point ) ) ); 00321 } 00322 00323 private Real get_point_polygon_vertex_distance( 00324 Point *point, 00325 polygons_struct *polygons, 00326 int poly_index, 00327 int *object_vertex ) 00328 { 00329 Point points[MAX_POINTS]; 00330 Real dist, best_dist; 00331 int i, size, point_index; 00332 00333 if( polygons->visibilities == (Smallest_int *) 0 || 00334 polygons->visibilities[poly_index] ) 00335 { 00336 size = get_polygon_points( polygons, poly_index, points ); 00337 00338 best_dist = 0.0; 00339 for_less( i, 0, size ) 00340 { 00341 point_index = polygons->indices[ 00342 POINT_INDEX(polygons->end_indices,poly_index,i)]; 00343 00344 dist = distance_between_points( point, 00345 &polygons->points[point_index] ); 00346 00347 if( i == 0 || dist < best_dist ) 00348 { 00349 best_dist = dist; 00350 *object_vertex = point_index; 00351 } 00352 } 00353 } 00354 else 00355 best_dist = 1.0e30; 00356 00357 return( best_dist ); 00358 } 00359 00360 public Real get_point_object_vertex_distance( 00361 Point *point, 00362 object_struct *object, 00363 int obj_index, 00364 int *object_vertex ) 00365 { 00366 Real dist; 00367 00368 if( get_object_type( object ) == POLYGONS ) 00369 { 00370 dist = get_point_polygon_vertex_distance( point, 00371 get_polygons_ptr(object), obj_index, object_vertex ); 00372 } 00373 else 00374 { 00375 print_error( 00376 "not implemented type in get_point_object_vertex_distance()n" ); 00377 dist = 1.0e30; 00378 } 00379 00380 return( dist ); 00381 } 00382 00383 /* ----------------------------- MNI Header ----------------------------------- 00384 @NAME : find_closest_point_on_object 00385 @INPUT : point 00386 object 00387 @OUTPUT : obj_index 00388 point_on_object 00389 @RETURNS : distance 00390 @DESCRIPTION: Finds the closest point on the object, and the index of the 00391 object component where it was found. 00392 @METHOD : 00393 @GLOBALS : 00394 @CALLS : 00395 @CREATED : 1993 David MacDonald 00396 @MODIFIED : 00397 ---------------------------------------------------------------------------- */ 00398 00399 public Real find_closest_point_on_object( 00400 Point *point, 00401 object_struct *object, 00402 int *obj_index, 00403 Point *point_on_object ) 00404 { 00405 Real closest_dist, dist; 00406 Point obj_point; 00407 lines_struct *lines; 00408 polygons_struct *polygons; 00409 quadmesh_struct *quadmesh; 00410 int i, m, n, n_objects; 00411 00412 if( obj_index != (int *) NULL ) 00413 *obj_index = -1; 00414 00415 switch( get_object_type( object ) ) 00416 { 00417 case LINES: 00418 lines = get_lines_ptr( object ); 00419 if( lines->n_items == 0 ) 00420 { 00421 n_objects = 0; 00422 break; 00423 } 00424 00425 if( lines->bintree != (bintree_struct_ptr) NULL ) 00426 { 00427 return( find_closest_point_in_bintree( point, lines->bintree, 00428 object, obj_index, point_on_object ) ); 00429 } 00430 00431 n_objects = lines->end_indices[lines->n_items-1] - lines->n_items; 00432 break; 00433 00434 case POLYGONS: 00435 polygons = get_polygons_ptr( object ); 00436 if( polygons->bintree != (bintree_struct_ptr) NULL ) 00437 { 00438 return( find_closest_point_in_bintree( point, polygons->bintree, 00439 object, obj_index, point_on_object ) ); 00440 } 00441 n_objects = polygons->n_items; 00442 break; 00443 00444 case QUADMESH: 00445 quadmesh = get_quadmesh_ptr( object ); 00446 if( quadmesh->bintree != (bintree_struct_ptr) NULL ) 00447 { 00448 return( find_closest_point_in_bintree( point, quadmesh->bintree, 00449 object, obj_index, point_on_object ) ); 00450 } 00451 get_quadmesh_n_objects( quadmesh, &m, &n ); 00452 n_objects = m * n; 00453 break; 00454 00455 case MARKER: 00456 n_objects = 1; 00457 break; 00458 00459 default: 00460 n_objects = 0; 00461 break; 00462 } 00463 00464 closest_dist = 0.0; 00465 for_less( i, 0, n_objects ) 00466 { 00467 dist = get_point_object_distance( point, object, i, &obj_point); 00468 00469 if( i == 0 || dist < closest_dist ) 00470 { 00471 closest_dist = dist; 00472 *obj_index = i; 00473 *point_on_object = obj_point; 00474 } 00475 } 00476 00477 return( closest_dist ); 00478 } 00479 00480 public Real find_closest_vertex_on_object( 00481 Point *point, 00482 object_struct *object, 00483 int *vertex_on_object ) 00484 { 00485 Real closest_dist, dist; 00486 Point *points; 00487 int i, n_points; 00488 00489 if( get_object_type( object ) == POLYGONS && 00490 get_polygons_ptr( object )->bintree != (bintree_struct_ptr) NULL ) 00491 { 00492 closest_dist = find_closest_vertex_in_bintree( point, 00493 get_polygons_ptr( object )->bintree, 00494 object, vertex_on_object ); 00495 } 00496 else 00497 { 00498 n_points = get_object_points( object, &points ); 00499 closest_dist = 0.0; 00500 for_less( i, 0, n_points ) 00501 { 00502 dist = distance_between_points( point, &points[i] ); 00503 00504 if( i == 0 || dist < closest_dist ) 00505 { 00506 closest_dist = dist; 00507 *vertex_on_object = i; 00508 } 00509 } 00510 } 00511 00512 return( closest_dist ); 00513 }

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