Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
gp3.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: gp3.h 4702 2012-02-23 09:39:33Z gedikli $
00037  *
00038  */
00039 
00040 #ifndef PCL_GP3_H_
00041 #define PCL_GP3_H_
00042 
00043 // PCL includes
00044 #include "pcl/surface/reconstruction.h"
00045 
00046 #include "pcl/ros/conversions.h"
00047 #include "pcl/kdtree/kdtree.h"
00048 #include <pcl/kdtree/kdtree_flann.h>
00049 #include <pcl/PolygonMesh.h>
00050 #include <pcl/TextureMesh.h>
00051 #include <boost/function.hpp>
00052 
00053 #include <fstream>
00054 #include <iostream>
00055 
00056 // add by ktran to export update function
00057 #include <pcl/pcl_macros.h>
00058 #include <pcl/point_types.h>
00059 
00060 
00061 namespace pcl
00062 {
00063   // add by ktran for Kdtree_flaan search
00064   struct SearchPoint : public PointXYZ
00065   {
00066     SearchPoint(float x, float y, float z) {this->x=x; this->y=y; this->z=z;}
00067   };
00068 
00077   inline bool 
00078   isVisible (const Eigen::Vector2f &X, const Eigen::Vector2f &S1, const Eigen::Vector2f &S2, 
00079              const Eigen::Vector2f &R = Eigen::Vector2f::Zero ())
00080   {
00081     double a0 = S1[1] - S2[1];
00082     double b0 = S2[0] - S1[0];
00083     double c0 = S1[0]*S2[1] - S2[0]*S1[1];
00084     double a1 = -X[1];
00085     double b1 = X[0];
00086     double c1 = 0;
00087     if (R != Eigen::Vector2f::Zero())
00088     {
00089       a1 += R[1];
00090       b1 -= R[0];
00091       c1 = R[0]*X[1] - X[0]*R[1];
00092     }
00093     double div = a0*b1 - b0*a1;
00094     double x = (b0*c1 - b1*c0) / div;
00095     double y = (a1*c0 - a0*c1) / div;
00096 
00097     bool intersection_outside_XR;
00098     if (R == Eigen::Vector2f::Zero())
00099     {
00100       if (X[0] > 0)
00101         intersection_outside_XR = (x <= 0) || (x >= X[0]);
00102       else if (X[0] < 0)
00103         intersection_outside_XR = (x >= 0) || (x <= X[0]);
00104       else if (X[1] > 0)
00105         intersection_outside_XR = (y <= 0) || (y >= X[1]);
00106       else if (X[1] < 0)
00107         intersection_outside_XR = (y >= 0) || (y <= X[1]);
00108       else
00109         intersection_outside_XR = true;
00110     }
00111     else
00112     {
00113       if (X[0] > R[0])
00114         intersection_outside_XR = (x <= R[0]) || (x >= X[0]);
00115       else if (X[0] < R[0])
00116         intersection_outside_XR = (x >= R[0]) || (x <= X[0]);
00117       else if (X[1] > R[1])
00118         intersection_outside_XR = (y <= R[1]) || (y >= X[1]);
00119       else if (X[1] < R[1])
00120         intersection_outside_XR = (y >= R[1]) || (y <= X[1]);
00121       else
00122         intersection_outside_XR = true;
00123     }
00124     if (intersection_outside_XR)
00125       return true;
00126     else
00127     {
00128       if (S1[0] > S2[0])
00129         return (x <= S2[0]) || (x >= S1[0]);
00130       else if (S1[0] < S2[0])
00131         return (x >= S2[0]) || (x <= S1[0]);
00132       else if (S1[1] > S2[1])
00133         return (y <= S2[1]) || (y >= S1[1]);
00134       else if (S1[1] < S2[1])                                                                                                                     
00135         return (y >= S2[1]) || (y <= S1[1]);
00136       else
00137         return false;
00138     }
00139   }  
00140 
00147   template <typename PointInT>
00148   class GreedyProjectionTriangulation : public MeshConstruction<PointInT>
00149   {
00150     public:
00151       using MeshConstruction<PointInT>::tree_;
00152       using MeshConstruction<PointInT>::input_;
00153       using MeshConstruction<PointInT>::indices_;
00154 
00155       typedef typename pcl::KdTree<PointInT> KdTree;
00156       typedef typename pcl::KdTree<PointInT>::Ptr KdTreePtr;
00157 
00158       typedef pcl::PointCloud<PointInT> PointCloudIn;
00159       typedef typename PointCloudIn::Ptr PointCloudInPtr;
00160       typedef typename PointCloudIn::ConstPtr PointCloudInConstPtr;
00161 
00162       // FIXME this enum should have a type.  Not be anonymous. 
00163       // Otherplaces where consts are used probably should be fixed.
00164       enum 
00165       { 
00166         NONE = -1,    // not-defined
00167         FREE = 0,    
00168         FRINGE = 1,  
00169         BOUNDARY = 2,
00170         COMPLETED = 3
00171       };
00172     
00174       GreedyProjectionTriangulation () : mu_ (0), search_radius_ (0), // must be set by user
00175                                          nnn_ (100),
00176                                          minimum_angle_ (M_PI/18), // 10 degrees
00177                                          maximum_angle_ (2*M_PI/3), // 120 degrees
00178                                          eps_angle_(M_PI/4), //45 degrees,
00179                                          consistent_(false), consistent_ordering_ (false)
00180       {};
00181 
00186       inline void 
00187       setMu (double mu) { mu_ = mu; }
00188 
00190       inline double 
00191       getMu () { return (mu_); }
00192 
00196       inline void 
00197       setMaximumNearestNeighbors (int nnn) { nnn_ = nnn; }
00198 
00200       inline int 
00201       getMaximumNearestNeighbors () { return (nnn_); }
00202 
00207       inline void 
00208       setSearchRadius (double radius) { search_radius_ = radius; }
00209 
00211       inline double 
00212       getSearchRadius () { return (search_radius_); }
00213 
00218       inline void 
00219       setMinimumAngle (double minimum_angle) { minimum_angle_ = minimum_angle; }
00220 
00222       inline double 
00223       getMinimumAngle () { return (minimum_angle_); }
00224 
00229       inline void 
00230       setMaximumAngle (double maximum_angle) { maximum_angle_ = maximum_angle; }
00231 
00233       inline double 
00234       getMaximumAngle () { return (maximum_angle_); }
00235 
00241       inline void 
00242       setMaximumSurfaceAngle (double eps_angle) { eps_angle_ = eps_angle; }
00243 
00245       inline double 
00246       getMaximumSurfaceAngle () { return (eps_angle_); }
00247 
00251       inline void 
00252       setNormalConsistency (bool consistent) { consistent_ = consistent; }
00253 
00255       inline bool 
00256       getNormalConsistency () { return (consistent_); }
00257 
00262       inline void 
00263       setConsistentVertexOrdering (bool consistent_ordering) { consistent_ordering_ = consistent_ordering; }
00264 
00266       inline bool 
00267       getConsistentVertexOrdering () { return (consistent_ordering_); }
00268 
00272       inline std::vector<int> 
00273       getPointStates () { return (state_); }
00274 
00278       inline std::vector<int> 
00279       getPartIDs () { return (part_); }
00280 
00281 
00283       inline std::vector<int>
00284       getSFN () { return (sfn_); }
00285 
00287       inline std::vector<int>
00288       getFFN () { return (ffn_); }
00289 
00294       void
00295       removeOverlapTriangles (pcl::PolygonMesh &mesh1, pcl::PolygonMesh &mesh2);
00296 
00297     protected:
00299       double mu_;
00300 
00302       double search_radius_;
00303 
00305       int nnn_;
00306 
00308       double minimum_angle_;
00309 
00311       double maximum_angle_;
00312 
00314       double eps_angle_;
00315 
00317       bool consistent_;
00318       
00320       bool consistent_ordering_;
00321 
00322      private:
00324       struct nnAngle
00325       {
00326         double angle;
00327         int index;
00328         int nnIndex;
00329         bool visible;
00330       };
00331 
00333       struct doubleEdge
00334       {
00335         int index;
00336         Eigen::Vector2f first;
00337         Eigen::Vector2f second;
00338       };
00339 
00340       // Variables made global to decrease the number of parameters to helper functions
00341 
00343       pcl::Vertices triangle_;
00345       std::vector<Eigen::Vector3f> coords_;
00346 
00348       std::vector<nnAngle> angles_;
00350       int R_;
00352       std::vector<int> state_;
00354       std::vector<int> source_;
00356       std::vector<int> ffn_;
00358       std::vector<int> sfn_;
00360       std::vector<int> part_;
00362       std::vector<int> fringe_queue_;
00363 
00365       bool is_current_free_;
00367       int current_index_;
00369       bool prev_is_ffn_;
00371       bool prev_is_sfn_;
00373       bool next_is_ffn_;
00375       bool next_is_sfn_;
00377       bool changed_1st_fn_;
00379       bool changed_2nd_fn_;
00381       int new2boundary_;
00382       
00386       bool already_connected_; 
00387 
00389       Eigen::Vector3f proj_qp_;
00391       Eigen::Vector3f u_;
00393       Eigen::Vector3f v_;
00395       Eigen::Vector2f uvn_ffn_;
00397       Eigen::Vector2f uvn_sfn_;
00399       Eigen::Vector2f uvn_next_ffn_;
00401       Eigen::Vector2f uvn_next_sfn_;
00402 
00404       Eigen::Vector3f tmp_;
00405 
00409       void 
00410       performReconstruction (pcl::PolygonMesh &output);
00411 
00415       void 
00416       performReconstruction (std::vector<pcl::Vertices> &polygons);
00417 
00421       bool
00422       reconstructPolygons (std::vector<pcl::Vertices> &polygons);
00423 
00425       std::string 
00426       getClassName () const { return ("GreedyProjectionTriangulation"); }
00427 
00438       void 
00439       connectPoint (std::vector<pcl::Vertices> &polygons, 
00440                     const int prev_index, 
00441                     const int next_index, 
00442                     const int next_next_index, 
00443                     const Eigen::Vector2f &uvn_current, 
00444                     const Eigen::Vector2f &uvn_prev, 
00445                     const Eigen::Vector2f &uvn_next);
00446 
00451       void 
00452       closeTriangle (std::vector<pcl::Vertices> &polygons);
00453 
00457       std::vector<std::vector<size_t> >
00458       getTriangleList (const pcl::PolygonMesh &input);
00459 
00466       inline void
00467       addTriangle (int a, int b, int c, std::vector<pcl::Vertices> &polygons)
00468       {
00469         triangle_.vertices.resize (3);
00470         if (consistent_ordering_)
00471         {
00472           const PointInT p = input_->at (indices_->at (a));
00473           const Eigen::Vector3f pv = p.getVector3fMap ();
00474           if (p.getNormalVector3fMap ().dot (
00475                 (pv - input_->at (indices_->at (b)).getVector3fMap ()).cross (
00476                  pv - input_->at (indices_->at (c)).getVector3fMap ()) ) > 0)
00477           {
00478             triangle_.vertices[0] = a;
00479             triangle_.vertices[1] = b;
00480             triangle_.vertices[2] = c;
00481           }
00482           else
00483           {
00484             triangle_.vertices[0] = a;
00485             triangle_.vertices[1] = c;
00486             triangle_.vertices[2] = b;
00487           }
00488         }
00489         else
00490         {
00491           triangle_.vertices[0] = a;
00492           triangle_.vertices[1] = b;
00493           triangle_.vertices[2] = c;
00494         }
00495         polygons.push_back (triangle_);
00496       }
00497 
00502       inline void
00503       addFringePoint (int v, int s)
00504       {
00505         source_[v] = s;
00506         part_[v] = part_[s];
00507         fringe_queue_.push_back(v);
00508       }
00509 
00515       static inline bool 
00516       nnAngleSortAsc (const nnAngle& a1, const nnAngle& a2)
00517       {
00518         if (a1.visible == a2.visible)
00519           return (a1.angle < a2.angle);
00520         else
00521           return a1.visible;
00522       }
00523   };
00524 
00525 } // namespace pcl
00526 
00527 #endif  //#ifndef PCL_GP3_H_
00528