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/poly_dist.c,v 1.9 2000/02/06 15:30:16 stever Exp $";
00020
#endif
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 public Real
sq_distance_between_points(
00037 Point *p1,
00038 Point *p2 )
00039 {
00040 Real dx, dy, dz;
00041
00042 dx = RPoint_x(*p1) - RPoint_x(*p2);
00043 dy = RPoint_y(*p1) - RPoint_y(*p2);
00044 dz = RPoint_z(*p1) - RPoint_z(*p2);
00045
00046
return( dx * dx + dy * dy + dz * dz );
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 private Real
point_segment_sq_distance(
00065 Point *p,
00066 Point *q1,
00067 Point *q2,
00068 Point *closest_point )
00069 {
00070
get_closest_point_on_line_segment( p, q1, q2, closest_point );
00071
00072
return(
sq_distance_between_points( p, closest_point ) );
00073 }
00074
00075 public Real
find_point_polygon_distance_sq(
00076 Point *point,
00077
int n_points,
00078 Point poly_points[],
00079 Point *closest_point )
00080 {
00081
int i, closest;
00082 Real n_dot_n, t, closest_dist, dist, d1, d2;
00083 Vector offset, o_a, normal;
00084 Point seg1_point, seg2_point;
00085
00086
00087
00088
find_polygon_normal( n_points, poly_points, &normal );
00089
00090 n_dot_n = DOT_VECTORS( normal, normal );
00091
if( n_dot_n == 0.0 )
00092 {
00093 fill_Point( *closest_point, 0.0, 0.0, 0.0 );
00094
return( 1.0e30 );
00095 }
00096
00097 SUB_POINTS( o_a, poly_points[0], *point );
00098
00099 t = DOT_VECTORS( o_a, normal ) / n_dot_n;
00100
00101 SCALE_VECTOR( offset, normal, t );
00102 ADD_POINT_VECTOR( *closest_point, *point, offset );
00103
00104
00105
00106
00107
if(
point_within_polygon( closest_point, n_points, poly_points, &normal ) )
00108
return( DOT_VECTORS( offset, offset ) );
00109
00110
00111
00112 closest = 0;
00113 closest_dist = 0.0;
00114
00115 for_less( i, 0, n_points )
00116 {
00117 dist =
sq_distance_between_points( point, &poly_points[i] );
00118
if( i == 0 || dist < closest_dist )
00119 {
00120 closest = i;
00121 closest_dist = dist;
00122 }
00123 }
00124
00125
00126
00127
00128 d1 =
point_segment_sq_distance( point,
00129 &poly_points[(closest-1+n_points)%n_points],
00130 &poly_points[closest], &seg1_point );
00131 d2 =
point_segment_sq_distance( point,
00132 &poly_points[closest],
00133 &poly_points[(closest+1)%n_points],
00134 &seg2_point );
00135
00136
if( d1 < d2 )
00137 {
00138 *closest_point = seg1_point;
00139 closest_dist = d1;
00140 }
00141
else
00142 {
00143 *closest_point = seg2_point;
00144 closest_dist = d2;
00145 }
00146
00147
return( closest_dist );
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 public Real
find_point_polygon_distance(
00166 Point *point,
00167
int n_points,
00168 Point poly_points[],
00169 Point *closest_point )
00170 {
00171
return( sqrt(
find_point_polygon_distance_sq( point, n_points, poly_points,
00172 closest_point ) ) );
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 public int find_closest_polygon_point(
00191 Point *point,
00192
polygons_struct *polygons,
00193 Point *closest_point )
00194 {
00195
int poly, size, closest_poly;
00196 Real dist, closest_dist;
00197 Point poly_points[
MAX_POINTS_PER_POLYGON], closest, best;
00198
object_struct object;
00199
00200 closest_dist = 0.0;
00201
00202
if( polygons->
bintree != NULL )
00203 {
00204 object.
object_type =
POLYGONS;
00205 object.
specific.polygons = *polygons;
00206 (
void)
find_closest_point_on_object( point, &object, &closest_poly,
00207 &best );
00208 }
00209
else
00210 {
00211 for_less( poly, 0, polygons->
n_items )
00212 {
00213 size =
get_polygon_points( polygons, poly, poly_points );
00214 dist =
find_point_polygon_distance_sq( point, size, poly_points,
00215 &closest);
00216
if( poly == 0 || dist < closest_dist )
00217 {
00218 closest_poly = poly;
00219 closest_dist = dist;
00220 best = closest;
00221 }
00222 }
00223 }
00224
00225 *closest_point = best;
00226
00227
return( closest_poly );
00228 }