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

poly_dist.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/poly_dist.c,v 1.9 2000/02/06 15:30:16 stever Exp $"; 00020 #endif 00021 00022 /* ----------------------------- MNI Header ----------------------------------- 00023 @NAME : sq_distance_between_points 00024 @INPUT : p1 00025 p2 00026 @OUTPUT : 00027 @RETURNS : squared distance between the points 00028 @DESCRIPTION: 00029 @METHOD : 00030 @GLOBALS : 00031 @CALLS : 00032 @CREATED : 1993 David MacDonald 00033 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00050 @NAME : point_segment_sq_distance 00051 @INPUT : p 00052 q1 00053 q2 00054 @OUTPUT : closest_point 00055 @RETURNS : squared distance 00056 @DESCRIPTION: Returns the squared distance from a point to a line segment. 00057 @METHOD : 00058 @GLOBALS : 00059 @CALLS : 00060 @CREATED : 1993 David MacDonald 00061 @MODIFIED : 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 /*--- first, find closest point on plane of polygon */ 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 /*--- if closest point on plane of polygon is within the polygon, then 00105 it is the closest point of the polygon */ 00106 00107 if( point_within_polygon( closest_point, n_points, poly_points, &normal ) ) 00108 return( DOT_VECTORS( offset, offset ) ); 00109 00110 /*--- find the vertex of the polygon which is closest */ 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 /*--- the closest point is on one of the two polygon edges touching the 00126 closest vertex */ 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 /* ----------------------------- MNI Header ----------------------------------- 00151 @NAME : find_point_polygon_distance 00152 @INPUT : point 00153 n_points 00154 poly_points 00155 @OUTPUT : closest_point 00156 @RETURNS : distance 00157 @DESCRIPTION: Returns the closest distance of a point to a polygon. 00158 @METHOD : 00159 @GLOBALS : 00160 @CALLS : 00161 @CREATED : 1993 David MacDonald 00162 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00176 @NAME : find_closest_polygon_point 00177 @INPUT : point 00178 polygons 00179 @OUTPUT : closest_point 00180 @RETURNS : index of polygon 00181 @DESCRIPTION: Finds the closest point on a polygons struct, returning the 00182 index of the polygon which has the closest point. 00183 @METHOD : 00184 @GLOBALS : 00185 @CALLS : 00186 @CREATED : 1993 David MacDonald 00187 @MODIFIED : 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 }

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