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
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef PCL_GP3_H_
00039 #define PCL_GP3_H_
00040
00041
00042 #include "pcl/surface/reconstruction.h"
00043
00044 #include "pcl/ros/conversions.h"
00045 #include "pcl/kdtree/kdtree.h"
00046 #include <pcl/PolygonMesh.h>
00047 #include <boost/function.hpp>
00048
00049 #include "pcl/io/io.h"
00050 #include <fstream>
00051 #include <iostream>
00052
00053 namespace pcl
00054 {
00060 template <typename PointInT>
00061 class GreedyProjectionTriangulation : public SurfaceReconstruction<PointInT>
00062 {
00063 public:
00064 using SurfaceReconstruction<PointInT>::tree_;
00065 using SurfaceReconstruction<PointInT>::input_;
00066 using SurfaceReconstruction<PointInT>::indices_;
00067 using SurfaceReconstruction<PointInT>::search_method_;
00068
00069 typedef typename pcl::KdTree<PointInT> KdTree;
00070 typedef typename pcl::KdTree<PointInT>::Ptr KdTreePtr;
00071
00072 typedef pcl::PointCloud<PointInT> PointCloudIn;
00073 typedef typename PointCloudIn::Ptr PointCloudInPtr;
00074 typedef typename PointCloudIn::ConstPtr PointCloudInConstPtr;
00075
00076
00077
00078 enum {
00079 NONE = -1,
00080 FREE = 0,
00081 FRINGE = 1,
00082 BOUNDARY = 2,
00083 COMPLETED = 3,
00084 };
00085
00087 GreedyProjectionTriangulation () : nnn_ (0), mu_ (0), search_radius_ (0),
00088 minimum_angle_ (0), maximum_angle_ (0),
00089 eps_angle_(0), consistent_(false)
00090 {};
00091
00096 inline void
00097 setMu (double mu) { mu_ = mu; }
00098
00100 inline double
00101 getMu () { return (mu_); }
00102
00106 inline void
00107 setMaximumNearestNeighbors (int nnn) { nnn_ = nnn; }
00108
00110 inline int
00111 getMaximumNearestNeighbors () { return (nnn_); }
00112
00117 inline void
00118 setSearchRadius (double radius) { search_radius_ = radius; }
00119
00121 inline double
00122 getSearchRadius () { return (search_radius_); }
00123
00128 inline void
00129 setMinimumAngle (double minimum_angle) { minimum_angle_ = minimum_angle; }
00130
00132 inline double
00133 getMinimumAngle () { return (minimum_angle_); }
00134
00139 inline void
00140 setMaximumAngle (double maximum_angle) { maximum_angle_ = maximum_angle; }
00141
00143 inline double
00144 getMaximumAngle () { return (maximum_angle_); }
00145
00151 inline void
00152 setMaximumSurfaceAgle (double eps_angle) { eps_angle_ = eps_angle; }
00153
00155 inline double
00156 getMaximumSurfaceAngle () { return (eps_angle_); }
00157
00161 inline void
00162 setNormalConsistency (bool consistent) { consistent_ = consistent; }
00163
00165 inline bool
00166 getNormalConsistency () { return (consistent_); }
00167
00171 inline std::vector<int>
00172 getPointStates () { return (state_); }
00173
00177 inline std::vector<int>
00178 getPartIDs () { return (part_); }
00179
00180 protected:
00182 int nnn_;
00183
00185 double mu_;
00186
00188 double search_radius_;
00189
00191 double minimum_angle_;
00192
00194 double maximum_angle_;
00195
00197 double eps_angle_;
00198
00200 bool consistent_;
00201
00210 inline int
00211 searchForNeighbors (int index, std::vector<int> &indices, std::vector<float> &distances)
00212 {
00213 return (search_method_ (index, nnn_, indices, distances));
00214 }
00215
00216 private:
00218 struct nnAngle
00219 {
00220 double angle;
00221 int index;
00222 int nnIndex;
00223 bool visible;
00224 };
00225
00227 struct doubleEdge
00228 {
00229 int index;
00230 Eigen::Vector2f first;
00231 Eigen::Vector2f second;
00232 };
00233
00234
00235
00237 pcl::Vertices triangle_;
00239 std::vector<Eigen::Vector3f> coords_;
00240
00242 std::vector<nnAngle> angles_;
00244 int R_;
00246 std::vector<int> state_;
00248 std::vector<int> source_;
00250 std::vector<int> ffn_;
00252 std::vector<int> sfn_;
00254 std::vector<int> part_;
00256 std::vector<int> fringe_queue_;
00257
00259 bool is_current_free_;
00261 int current_index_;
00263 bool prev_is_ffn_;
00265 bool prev_is_sfn_;
00267 bool next_is_ffn_;
00269 bool next_is_sfn_;
00271 bool changed_1st_fn_;
00273 bool changed_2nd_fn_;
00275 int new2boundary_;
00276
00280 bool already_connected_;
00281
00283 Eigen::Vector3f proj_qp_;
00285 Eigen::Vector3f u_;
00287 Eigen::Vector3f v_;
00289 Eigen::Vector2f uvn_ffn_;
00291 Eigen::Vector2f uvn_sfn_;
00293 Eigen::Vector2f uvn_next_ffn_;
00295 Eigen::Vector2f uvn_next_sfn_;
00296
00298 Eigen::Vector3f tmp_;
00299
00303 void
00304 performReconstruction (pcl::PolygonMesh &output);
00305
00307 std::string
00308 getClassName () const { return ("GreedyProjectionTriangulation"); }
00309
00320 void
00321 connectPoint (pcl::PolygonMesh &output,
00322 const int prev_index,
00323 const int next_index,
00324 const int next_next_index,
00325 const Eigen::Vector2f &uvn_current,
00326 const Eigen::Vector2f &uvn_prev,
00327 const Eigen::Vector2f &uvn_next);
00328
00333 void
00334 closeTriangle (pcl::PolygonMesh &output);
00335
00342 inline void
00343 addTriangle (int a, int b, int c, pcl::PolygonMesh &output)
00344 {
00345 triangle_.vertices.clear ();
00346 triangle_.vertices.push_back (a);
00347 triangle_.vertices.push_back (b);
00348 triangle_.vertices.push_back (c);
00349 output.polygons.push_back(triangle_);
00350 }
00351
00356 inline void
00357 addFringePoint (int v, int s)
00358 {
00359 source_[v] = s;
00360 part_[v] = part_[s];
00361 fringe_queue_.push_back(v);
00362 }
00363
00368 static inline bool
00369 nnAngleSortAsc (const nnAngle& a1, const nnAngle& a2)
00370 {
00371 if (a1.visible == a2.visible)
00372 return (a1.angle < a2.angle);
00373 else
00374 return a1.visible;
00375 }
00376
00384 inline bool
00385 isVisible (const Eigen::Vector2f &X, const Eigen::Vector2f &S1, const Eigen::Vector2f &S2,
00386 const Eigen::Vector2f &R = Eigen::Vector2f::Zero ())
00387 {
00388 double a0 = S1[1] - S2[1];
00389 double b0 = S2[0] - S1[0];
00390 double c0 = S1[0]*S2[1] - S2[0]*S1[1];
00391 double a1 = -X[1];
00392 double b1 = X[0];
00393 double c1 = 0;
00394 if (R != Eigen::Vector2f::Zero())
00395 {
00396 a1 += R[1];
00397 b1 -= R[0];
00398 c1 = R[0]*X[1] - X[0]*R[1];
00399 }
00400 double div = a0*b1 - b0*a1;
00401 double x = (b0*c1 - b1*c0) / div;
00402 double y = (a1*c0 - a0*c1) / div;
00403
00404 bool intersection_outside_XR;
00405 if (R == Eigen::Vector2f::Zero())
00406 {
00407 if (X[0] > 0)
00408 intersection_outside_XR = (x <= 0) || (x >= X[0]);
00409 else if (X[0] < 0)
00410 intersection_outside_XR = (x >= 0) || (x <= X[0]);
00411 else if (X[1] > 0)
00412 intersection_outside_XR = (y <= 0) || (y >= X[1]);
00413 else if (X[1] < 0)
00414 intersection_outside_XR = (y >= 0) || (y <= X[1]);
00415 else
00416 intersection_outside_XR = true;
00417 }
00418 else
00419 {
00420 if (X[0] > R[0])
00421 intersection_outside_XR = (x <= R[0]) || (x >= X[0]);
00422 else if (X[0] < R[0])
00423 intersection_outside_XR = (x >= R[0]) || (x <= X[0]);
00424 else if (X[1] > R[1])
00425 intersection_outside_XR = (y <= R[1]) || (y >= X[1]);
00426 else if (X[1] < R[1])
00427 intersection_outside_XR = (y >= R[1]) || (y <= X[1]);
00428 else
00429 intersection_outside_XR = true;
00430 }
00431 if (intersection_outside_XR)
00432 return true;
00433 else
00434 {
00435 if (S1[0] > S2[0])
00436 return (x <= S2[0]) || (x >= S1[0]);
00437 else if (S1[0] < S2[0])
00438 return (x >= S2[0]) || (x <= S1[0]);
00439 else if (S1[1] > S2[1])
00440 return (y <= S2[1]) || (y >= S1[1]);
00441 else if (S1[1] < S2[1])
00442 return (y >= S2[1]) || (y <= S1[1]);
00443 else
00444 return false;
00445 }
00446 }
00447 };
00448
00449 }
00450
00451 #endif //#ifndef PCL_GP3_H_