Point Cloud Library (PCL)  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
plane_clipper3D.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2009, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00035 #ifndef PCL_FILTERS_IMPL_PLANE_CLIPPER3D_HPP
00036 #define PCL_FILTERS_IMPL_PLANE_CLIPPER3D_HPP
00037 
00038 #include "pcl/filters/plane_clipper3D.h"
00039 
00040 template<typename PointT>
00041 pcl::PlaneClipper3D<PointT>::PlaneClipper3D (Eigen::Vector4f plane_params)
00042 : plane_params_ (plane_params)
00043 {
00044 }
00045 
00046 template<typename PointT>
00047 pcl::PlaneClipper3D<PointT>::~PlaneClipper3D () throw ()
00048 {
00049 }
00050 
00051 template<typename PointT> float
00052 pcl::PlaneClipper3D<PointT>::getDistance (const PointT& point) const
00053 {
00054   return (plane_params_[0] * point.x + plane_params_[1] * point.y + plane_params_[2] * point.z + plane_params_[3]);
00055 }
00056 
00057 template<typename PointT> bool
00058 pcl::PlaneClipper3D<PointT>::clipPoint3D (const PointT& point) const
00059 {
00060   return ((plane_params_[0] * point.x + plane_params_[1] * point.y + plane_params_[2] * point.z ) >= -plane_params_[3]);
00061 }
00062 
00066 template<typename PointT> bool
00067 pcl::PlaneClipper3D<PointT>::clipLineSegment3D (PointT& point1, PointT& point2) const
00068 {
00069   float dist1 = getDistance (point1);
00070   float dist2 = getDistance (point2);
00071 
00072   if (dist1 * dist2 > 0) // both on same side of the plane -> nothing to clip
00073     return (dist1 > 0); // true if both are on positive side, thus visible
00074 
00075   float lambda = dist2 / (dist2 - dist1);
00076 
00077   // get the plane intersecion
00078   PointT intersection;
00079   intersection.x = (point1.x - point2.x) * lambda + point2.x;
00080   intersection.y = (point1.y - point2.y) * lambda + point2.y;
00081   intersection.z = (point1.z - point2.z) * lambda + point2.z;
00082 
00083   // point1 is visible, point2 not => point2 needs to be replaced by intersection
00084   if (dist1 >= 0)
00085     point2 = intersection;
00086   else
00087     point1 = intersection;
00088 
00089   return false;
00090 }
00091 
00095 template<typename PointT> void
00096 pcl::PlaneClipper3D<PointT>::clipPlanarPolygon3D (std::vector<PointT>& polygon) const
00097 {
00098   // test for degenerated polygons
00099   if (polygon.size () < 3)
00100   {
00101     if (polygon.size () == 1)
00102     {
00103       // point outside clipping area ?
00104       if (!clipPoint3D (polygon [0]))
00105         polygon.clear ();
00106     }
00107     else if (polygon.size () == 2)
00108     {
00109       if (!clipLineSegment3D (polygon [0], polygon [1]))
00110         polygon.clear ();
00111     }
00112     return;
00113   }
00114 
00115   std::vector<PointT> clipped;
00116   clipped.reserve (polygon.size ());
00117 
00118   float previous_distance = getDistance (polygon [0]);
00119 
00120   if (previous_distance > 0)
00121     clipped.push_back (polygon [0]);
00122 
00123   for (typename std::vector<PointT>::iterator pIt = polygon.begin () + 1; pIt != polygon.end (); ++pIt)
00124   {
00125     // if we intersect plane
00126     float distance = getDistance (*pIt);
00127     if (distance * previous_distance < 0)
00128     {
00129       float lambda = distance / (distance - previous_distance);
00130 
00131       // get the plane intersecion
00132       typename std::vector<PointT>::iterator prev_it = pIt - 1;
00133       PointT intersection;
00134       intersection.x = (prev_it->x - pIt->x) * lambda + pIt->x;
00135       intersection.y = (prev_it->y - pIt->y) * lambda + pIt->y;
00136       intersection.z = (prev_it->z - pIt->z) * lambda + pIt->z;
00137 
00138       clipped.push_back (intersection);
00139     }
00140     if (distance > 0)
00141       clipped.push_back (*pIt);
00142 
00143     previous_distance = distance;
00144   }
00145 }
00146 
00147 template<typename PointT> void
00148 pcl::PlaneClipper3D<PointT>::clipPointCloud3D (const pcl::PointCloud<PointT>& cloud_in, std::vector<int>& clipped, const std::vector<int>& indices) const
00149 {
00150   if (indices.empty ())
00151   {
00152     clipped.reserve (cloud_in.size ());
00153     /*
00154 #if 0
00155     Eigen::MatrixXf points = cloud_in.getMatrixXfMap (4, sizeof (PointT) / sizeof (float), offsetof(PointT,x) / sizeof (float));
00156     Eigen::VectorXf distances = plane_params_.transpose () * points;
00157     for (register unsigned rIdx = 0; rIdx < cloud_in.size (); ++ rIdx)
00158     {
00159       if (distances (rIdx, 0) >= -plane_params_[3])
00160         clipped.push_back (rIdx);
00161     }
00162 #else
00163     Eigen::Matrix4Xf points (4, cloud_in.size ());
00164     for (register unsigned rIdx = 0; rIdx < cloud_in.size (); ++ rIdx)
00165     {
00166       points (0, rIdx) = cloud_in[rIdx].x;
00167       points (1, rIdx) = cloud_in[rIdx].y;
00168       points (2, rIdx) = cloud_in[rIdx].z;
00169       points (3, rIdx) = 1;
00170     }
00171     Eigen::VectorXf distances = plane_params_.transpose () * points;
00172     for (register unsigned rIdx = 0; rIdx < cloud_in.size (); ++ rIdx)
00173     {
00174       if (distances (rIdx, 0) >= 0)
00175         clipped.push_back (rIdx);
00176     }
00177 
00178 #endif
00179 
00180     //cout << "points   : " << points.rows () << " x " << points.cols () << " * " << plane_params_.transpose ().rows () << " x " << plane_params_.transpose ().cols () << endl;
00181 
00182     //cout << "distances: " << distances.rows () << " x " << distances.cols () << endl;
00183     /*/
00184     for (register unsigned pIdx = 0; pIdx < cloud_in.size (); ++pIdx)
00185     {
00186       if (clipPoint3D (cloud_in[pIdx]))
00187         clipped.push_back (pIdx);
00188     }
00189     //*/
00190   }
00191 }
00192 #endif //PCL_FILTERS_IMPL_PLANE_CLIPPER3D_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines