00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
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
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
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
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
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
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
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
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
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
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
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
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
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
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
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 }