00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00033 #include "door_handle_detector/geometry/point.h"
00034 #include "door_handle_detector/geometry/intersections.h"
00035 #include "door_handle_detector/geometry/distances.h"
00036
00037 #include <cfloat>
00038
00039 namespace cloud_geometry
00040 {
00041
00042 namespace intersections
00043 {
00045
00051 bool
00052 planeWithPlaneIntersection (const std::vector<double> &plane_a, const std::vector<double> &plane_b,
00053 std::vector<double> &line)
00054 {
00055 line.resize (6);
00056
00057 line[3] = plane_a.at (1) * plane_b.at (2) - plane_a.at (2) * plane_b.at (1);
00058 line[4] = plane_a.at (2) * plane_b.at (0) - plane_a.at (0) * plane_b.at (2);
00059 line[5] = plane_a.at (0) * plane_b.at (1) - plane_a.at (1) * plane_b.at (0);
00060
00061
00062 if (fabs (line[3]) > FLT_MIN)
00063 {
00064 line[0] = 0.0;
00065 line[1] = (plane_a.at (2) * plane_b.at (3) - plane_a.at (3) * plane_b.at (2)) / line[3];
00066 line[2] = (plane_a.at (3) * plane_b.at (1) - plane_a.at (1) * plane_b.at (3)) / line[3];
00067 }
00068 else if (fabs (line[4]) > FLT_MIN)
00069 {
00070 line[0] = (plane_a.at (3) * plane_b.at (2) - plane_a.at (2) * plane_b.at (3)) / line[4];
00071 line[1] = 0.0;
00072 line[2] = (plane_a.at (0) * plane_b.at (3) - plane_a.at (3) * plane_b.at (0)) / line[4];
00073 }
00074 else if (fabs (line[5]) > FLT_MIN)
00075 {
00076 line[0] = (plane_a.at (1) * plane_b.at (3) - plane_a.at (3) * plane_b.at (1)) / line[5];
00077 line[1] = (plane_a.at (3) * plane_b.at (0) - plane_a.at (0) * plane_b.at (3)) / line[5];
00078 line[2] = 0.0;
00079 }
00080 else
00081 {
00082 line.resize (0);
00083 return (false);
00084 }
00085 return (true);
00086 }
00087
00089
00095 bool
00096 lineWithPlaneIntersection (const std::vector<double> &plane, const std::vector<double> &line, geometry_msgs::Point32 &point)
00097 {
00098
00099 double dn = line.at (3) * plane.at (0) + line.at (4) * plane.at (1) + line.at (5) * plane.at (2);
00100
00101 if (fabs (dn) < 1e-7)
00102 return (false);
00103
00104
00105
00106 double w[3];
00107 w[0] = line.at (0) + (plane.at (3) * plane.at (0));
00108 w[1] = line.at (1) + (plane.at (3) * plane.at (1));
00109 w[2] = line.at (2) + (plane.at (3) * plane.at (2));
00110
00111
00112 double u = (plane.at (0) * w[0] + plane.at (1) * w[1] + plane.at (2) * w[2]) / dn;
00113 point.x = line.at (0) - u * line.at (3);
00114 point.y = line.at (1) - u * line.at (4);
00115 point.z = line.at (2) - u * line.at (5);
00116 return (true);
00117 }
00118
00120
00126 bool
00127 lineWithLineIntersection (const std::vector<double> &line_a, const std::vector<double> &line_b, geometry_msgs::Point32 &point,
00128 double sqr_eps)
00129 {
00130 std::vector<double> segment;
00131 cloud_geometry::distances::lineToLineSegment (line_a, line_b, segment);
00132
00133 double sqr_dist = (segment.at (0) - segment.at (3)) * (segment.at (0) - segment.at (3)) +
00134 (segment.at (1) - segment.at (4)) * (segment.at (1) - segment.at (4)) +
00135 (segment.at (2) - segment.at (5)) * (segment.at (2) - segment.at (5));
00136 if (sqr_dist < sqr_eps)
00137 {
00138 point.x = segment.at (0);
00139 point.y = segment.at (1);
00140 point.z = segment.at (2);
00141 return (true);
00142 }
00143 return (false);
00144 }
00145
00146
00148
00153 bool
00154 planeWithCubeIntersection (const std::vector<double> &plane, const std::vector<double> &cube, geometry_msgs::Polygon &polygon)
00155 {
00156 double width[3];
00157 for (int d = 0; d < 3; d++)
00158 width[d] = cube.at (d + 3) - cube.at (d);
00159
00160 double x[3];
00161 geometry_msgs::Point32 mean;
00162 mean.x = mean.y = mean.z = 0;
00163
00164
00165 for (int k = 0; k < 3; k++)
00166 {
00167 if (fabs (plane.at (k)) > 0)
00168 {
00169
00170 int i = (k + 1) % 3;
00171 int j = (k + 2) % 3;
00172
00173
00174 for (double w_i = 0; w_i <= width[i]; w_i += width[i])
00175 {
00176 x[i] = cube.at (i) + w_i;
00177
00178 for (double w_j = 0; w_j <= width[j]; w_j += width[j])
00179 {
00180 x[j] = cube.at (j) + w_j;
00181
00182
00183 x[k] = -(plane.at (3) + x[i] * plane.at (i) + x[j] * plane.at (j) ) / plane.at (k);
00184
00185
00186 if (x[k] >= cube.at (k) && x[k] <= cube.at (k + 3) )
00187 {
00188 geometry_msgs::Point32 ci;
00189 ci.x = x[0]; ci.y = x[1]; ci.z = x[2];
00190 polygon.points.push_back (ci);
00191
00192 mean.x += x[0]; mean.y += x[1]; mean.z += x[2];
00193 }
00194 }
00195 }
00196 }
00197 }
00198
00199 int npts = polygon.points.size ();
00200
00201 mean.x /= npts; mean.y /= npts; mean.z /= npts;
00202
00203
00204 for (int i = 0; i < npts; i++)
00205 {
00206 double a = atan2 (polygon.points[i].y - mean.y, polygon.points[i].x - mean.x);
00207 if (a < 0) a += 2*M_PI;
00208 for (int j = i+1; j < npts; j++)
00209 {
00210 double b = atan2 (polygon.points[j].y - mean.y, polygon.points[j].x - mean.x);
00211 if (b < 0) b += 2*M_PI;
00212 if (b < a)
00213 {
00214 double temp;
00215
00216 temp = polygon.points[j].x;
00217 polygon.points[j].x = polygon.points[i].x;
00218 polygon.points[i].x = temp;
00219
00220 temp = polygon.points[j].y;
00221 polygon.points[j].y = polygon.points[i].y;
00222 polygon.points[i].y = temp;
00223
00224 temp = polygon.points[j].z;
00225 polygon.points[j].z = polygon.points[i].z;
00226 polygon.points[i].z = temp;
00227
00228 a = b;
00229 }
00230 }
00231 }
00232 return (true);
00233 }
00234
00236
00241 bool
00242 lineToBoxIntersection (const std::vector<double> &line, const std::vector<double> &cube)
00243 {
00244 const int _right = 0, _left = 1, _middle = 2;
00245 bool inside = true;
00246 char quadrant[3];
00247 int which_plane = 0;
00248 double max_t[3], candidate_plane[3];
00249
00250
00251 for (int d = 0; d < 3; d++)
00252 {
00253 if (line.at (d) < cube.at (2*d))
00254 {
00255 quadrant[d] = _left;
00256 candidate_plane[d] = cube.at (2*d);
00257 inside = false;
00258 }
00259 else if (line.at (d) > cube.at (2*d+1))
00260 {
00261 quadrant[d] = _right;
00262 candidate_plane[d] = cube.at (2*d+1);
00263 inside = false;
00264 }
00265 else
00266 {
00267 quadrant[d] = _middle;
00268 }
00269 }
00270
00271
00272 if (inside)
00273 return (true);
00274
00275
00276 for (int d = 0; d < 3; d++)
00277 {
00278 if (quadrant[d] != _middle && line.at (d + 3) != 0.0)
00279 max_t[d] = (candidate_plane[d] - line.at (d)) / line.at (d + 3);
00280 else
00281 max_t[d] = -1.0;
00282 }
00283
00284
00285 for (int d = 0; d < 3; d++)
00286 if (max_t[which_plane] < max_t[d])
00287 which_plane = d;
00288
00289
00290 if (max_t[which_plane] > 1.0 || max_t[which_plane] < 0.0)
00291 return (false);
00292
00293
00294 for (int d = 0; d < 3; d++)
00295 {
00296 if (which_plane != d)
00297 {
00298 double coord = line.at (d) + max_t[which_plane] * line.at (d + 3);
00299 if ( coord < cube.at (2*d) || coord > cube.at (2*d+1) )
00300 return (false);
00301 }
00302 }
00303 return (true);
00304 }
00305
00307
00311 bool
00312 lineToCircleIntersection (const std::vector<double> &line, const std::vector<double> &circle)
00313 {
00314 double u = ((circle.at (0) - line[0]) * (line[3] - line[0]) +
00315 (circle.at (1) - line[1]) * (line[4] - line[1]) +
00316 (circle[2] - line[2]) * (line[5] - line[2]))
00317 /
00318 ( (line[3] - line[0]) * (line[3] - line[0]) +
00319 (line[4] - line[1]) * (line[4] - line[1]) +
00320 (line[5] - line[2]) * (line[5] - line[2])
00321 );
00322
00323
00324 geometry_msgs::Point32 pi;
00325 pi.x = line[0] + (line[3] - line[0]) * u;
00326 pi.y = line[0] + (line[4] - line[1]) * u;
00327 pi.z = line[0] + (line[5] - line[2]) * u;
00328
00329
00330 if (circle[3] * circle[3] < ( (circle[0] - pi.x) * (circle[0] - pi.x) +
00331 (circle[1] - pi.y) * (circle[1] - pi.y) +
00332 (circle[2] - pi.z) * (circle[2] - pi.z) ))
00333 return false;
00334
00335 if ((u >= 0) && (u <= 1))
00336 return true;
00337 else
00338 return false;
00339 }
00340
00341 }
00342 }