intersections.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 Radu Bogdan Rusu <rusu -=- cs.tum.edu>
00003  *
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025  * POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  * $Id$
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       // Compute dir = n1 x n2
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       // Find a point on both planes
00062       if (fabs (line[3]) > FLT_MIN)         // intersect line with the X = 0 plane
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)    // intersect line with the Y = 0 plane
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)    // intersect line with the Z = 0 plane
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       // line Direction * plane Normal
00099       double dn = line.at (3) * plane.at (0) + line.at (4) * plane.at (1) + line.at (5) * plane.at (2);
00100       // Check for parallelism
00101       if (fabs (dn) < 1e-7)
00102         return (false);
00103 
00104       // Get a point on the plane
00105       // w = P0 - V0
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       // point = P1 - (P0 - P1) . (d + n . P1) / [(P0-P1) . n];
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       // Keep one dimension constant
00165       for (int k = 0; k < 3; k++)
00166       {
00167         if (fabs (plane.at (k)) > 0)
00168         {
00169           // Get the other two dimensions
00170           int i = (k + 1) % 3;
00171           int j = (k + 2) % 3;
00172 
00173           // Iterate over another dimension
00174           for (double w_i = 0; w_i <= width[i]; w_i += width[i])
00175           {
00176             x[i] = cube.at (i) + w_i;
00177             // Iterate over another dimension
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               // Evaluate the plane equation for this point (plane[k]*x[k] + plane[i]*x[i] + plane[j]*x[j] + plane[3] = 0)
00183               x[k] = -(plane.at (3) + x[i] * plane.at (i) + x[j] * plane.at (j) ) / plane.at (k);
00184 
00185               // Check if in cell
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             } // for w_j
00195           } // for w_i
00196         }
00197       } // for k
00198 
00199       int npts = polygon.points.size ();
00200       // Compute the mean
00201       mean.x /= npts; mean.y /= npts; mean.z /= npts;
00202 
00203       // Sort the points so we create a convex polygon
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         } // for j
00231       } // for i
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;   // start by assuming that the line origin is inside the box
00246       char    quadrant[3];
00247       int     which_plane = 0;
00248       double  max_t[3], candidate_plane[3];
00249 
00250       //  First find closest planes
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       //  Check whether origin of ray is inside bbox
00272       if (inside)
00273         return (true);
00274 
00275       //  Calculate parametric distances to plane
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       //  Find the largest parametric value of intersection
00285       for (int d = 0; d < 3; d++)
00286         if (max_t[which_plane] < max_t[d])
00287           which_plane = d;
00288 
00289       //  Check for valid intersection along line
00290       if (max_t[which_plane] > 1.0 || max_t[which_plane] < 0.0)
00291         return (false);
00292 
00293       //  Intersection point along line is okay.  Check bbox.
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       // Compute the intersection point
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       // Check the distance between the center of the circle and the intersection point
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 }


door_handle_detector
Author(s): Radu Bogdan Rusu, Marius
autogenerated on Wed Dec 11 2013 14:17:00