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
00039
00040 #ifndef PCL_GP3_H_
00041 #define PCL_GP3_H_
00042
00043
00044 #include <pcl/surface/reconstruction.h>
00045 #include <pcl/surface/boost.h>
00046
00047 #include <pcl/conversions.h>
00048 #include <pcl/kdtree/kdtree.h>
00049 #include <pcl/kdtree/kdtree_flann.h>
00050 #include <pcl/PolygonMesh.h>
00051
00052 #include <fstream>
00053 #include <iostream>
00054
00055
00056
00057 namespace pcl
00058 {
00067 inline bool
00068 isVisible (const Eigen::Vector2f &X, const Eigen::Vector2f &S1, const Eigen::Vector2f &S2,
00069 const Eigen::Vector2f &R = Eigen::Vector2f::Zero ())
00070 {
00071 double a0 = S1[1] - S2[1];
00072 double b0 = S2[0] - S1[0];
00073 double c0 = S1[0]*S2[1] - S2[0]*S1[1];
00074 double a1 = -X[1];
00075 double b1 = X[0];
00076 double c1 = 0;
00077 if (R != Eigen::Vector2f::Zero())
00078 {
00079 a1 += R[1];
00080 b1 -= R[0];
00081 c1 = R[0]*X[1] - X[0]*R[1];
00082 }
00083 double div = a0*b1 - b0*a1;
00084 double x = (b0*c1 - b1*c0) / div;
00085 double y = (a1*c0 - a0*c1) / div;
00086
00087 bool intersection_outside_XR;
00088 if (R == Eigen::Vector2f::Zero())
00089 {
00090 if (X[0] > 0)
00091 intersection_outside_XR = (x <= 0) || (x >= X[0]);
00092 else if (X[0] < 0)
00093 intersection_outside_XR = (x >= 0) || (x <= X[0]);
00094 else if (X[1] > 0)
00095 intersection_outside_XR = (y <= 0) || (y >= X[1]);
00096 else if (X[1] < 0)
00097 intersection_outside_XR = (y >= 0) || (y <= X[1]);
00098 else
00099 intersection_outside_XR = true;
00100 }
00101 else
00102 {
00103 if (X[0] > R[0])
00104 intersection_outside_XR = (x <= R[0]) || (x >= X[0]);
00105 else if (X[0] < R[0])
00106 intersection_outside_XR = (x >= R[0]) || (x <= X[0]);
00107 else if (X[1] > R[1])
00108 intersection_outside_XR = (y <= R[1]) || (y >= X[1]);
00109 else if (X[1] < R[1])
00110 intersection_outside_XR = (y >= R[1]) || (y <= X[1]);
00111 else
00112 intersection_outside_XR = true;
00113 }
00114 if (intersection_outside_XR)
00115 return true;
00116 else
00117 {
00118 if (S1[0] > S2[0])
00119 return (x <= S2[0]) || (x >= S1[0]);
00120 else if (S1[0] < S2[0])
00121 return (x >= S2[0]) || (x <= S1[0]);
00122 else if (S1[1] > S2[1])
00123 return (y <= S2[1]) || (y >= S1[1]);
00124 else if (S1[1] < S2[1])
00125 return (y >= S2[1]) || (y <= S1[1]);
00126 else
00127 return false;
00128 }
00129 }
00130
00137 template <typename PointInT>
00138 class GreedyProjectionTriangulation : public MeshConstruction<PointInT>
00139 {
00140 public:
00141 typedef boost::shared_ptr<GreedyProjectionTriangulation<PointInT> > Ptr;
00142 typedef boost::shared_ptr<const GreedyProjectionTriangulation<PointInT> > ConstPtr;
00143
00144 using MeshConstruction<PointInT>::tree_;
00145 using MeshConstruction<PointInT>::input_;
00146 using MeshConstruction<PointInT>::indices_;
00147
00148 typedef typename pcl::KdTree<PointInT> KdTree;
00149 typedef typename pcl::KdTree<PointInT>::Ptr KdTreePtr;
00150
00151 typedef pcl::PointCloud<PointInT> PointCloudIn;
00152 typedef typename PointCloudIn::Ptr PointCloudInPtr;
00153 typedef typename PointCloudIn::ConstPtr PointCloudInConstPtr;
00154
00155 enum GP3Type
00156 {
00157 NONE = -1,
00158 FREE = 0,
00159 FRINGE = 1,
00160 BOUNDARY = 2,
00161 COMPLETED = 3
00162 };
00163
00165 GreedyProjectionTriangulation () :
00166 mu_ (0),
00167 search_radius_ (0),
00168 nnn_ (100),
00169 minimum_angle_ (M_PI/18),
00170 maximum_angle_ (2*M_PI/3),
00171 eps_angle_(M_PI/4),
00172 consistent_(false),
00173 consistent_ordering_ (false),
00174 triangle_ (),
00175 coords_ (),
00176 angles_ (),
00177 R_ (),
00178 state_ (),
00179 source_ (),
00180 ffn_ (),
00181 sfn_ (),
00182 part_ (),
00183 fringe_queue_ (),
00184 is_current_free_ (false),
00185 current_index_ (),
00186 prev_is_ffn_ (false),
00187 prev_is_sfn_ (false),
00188 next_is_ffn_ (false),
00189 next_is_sfn_ (false),
00190 changed_1st_fn_ (false),
00191 changed_2nd_fn_ (false),
00192 new2boundary_ (),
00193 already_connected_ (false),
00194 proj_qp_ (),
00195 u_ (),
00196 v_ (),
00197 uvn_ffn_ (),
00198 uvn_sfn_ (),
00199 uvn_next_ffn_ (),
00200 uvn_next_sfn_ (),
00201 tmp_ ()
00202 {};
00203
00208 inline void
00209 setMu (double mu) { mu_ = mu; }
00210
00212 inline double
00213 getMu () const { return (mu_); }
00214
00218 inline void
00219 setMaximumNearestNeighbors (int nnn) { nnn_ = nnn; }
00220
00222 inline int
00223 getMaximumNearestNeighbors () const { return (nnn_); }
00224
00229 inline void
00230 setSearchRadius (double radius) { search_radius_ = radius; }
00231
00233 inline double
00234 getSearchRadius () const { return (search_radius_); }
00235
00240 inline void
00241 setMinimumAngle (double minimum_angle) { minimum_angle_ = minimum_angle; }
00242
00244 inline double
00245 getMinimumAngle () const { return (minimum_angle_); }
00246
00251 inline void
00252 setMaximumAngle (double maximum_angle) { maximum_angle_ = maximum_angle; }
00253
00255 inline double
00256 getMaximumAngle () const { return (maximum_angle_); }
00257
00263 inline void
00264 setMaximumSurfaceAngle (double eps_angle) { eps_angle_ = eps_angle; }
00265
00267 inline double
00268 getMaximumSurfaceAngle () const { return (eps_angle_); }
00269
00273 inline void
00274 setNormalConsistency (bool consistent) { consistent_ = consistent; }
00275
00277 inline bool
00278 getNormalConsistency () const { return (consistent_); }
00279
00284 inline void
00285 setConsistentVertexOrdering (bool consistent_ordering) { consistent_ordering_ = consistent_ordering; }
00286
00288 inline bool
00289 getConsistentVertexOrdering () const { return (consistent_ordering_); }
00290
00294 inline std::vector<int>
00295 getPointStates () const { return (state_); }
00296
00300 inline std::vector<int>
00301 getPartIDs () const { return (part_); }
00302
00303
00305 inline std::vector<int>
00306 getSFN () const { return (sfn_); }
00307
00309 inline std::vector<int>
00310 getFFN () const { return (ffn_); }
00311
00312 protected:
00314 double mu_;
00315
00317 double search_radius_;
00318
00320 int nnn_;
00321
00323 double minimum_angle_;
00324
00326 double maximum_angle_;
00327
00329 double eps_angle_;
00330
00332 bool consistent_;
00333
00335 bool consistent_ordering_;
00336
00337 private:
00339 struct nnAngle
00340 {
00341 double angle;
00342 int index;
00343 int nnIndex;
00344 bool visible;
00345 };
00346
00348 struct doubleEdge
00349 {
00350 doubleEdge () : index (0), first (), second () {}
00351 int index;
00352 Eigen::Vector2f first;
00353 Eigen::Vector2f second;
00354 };
00355
00356
00357
00359 pcl::Vertices triangle_;
00361 std::vector<Eigen::Vector3f> coords_;
00362
00364 std::vector<nnAngle> angles_;
00366 int R_;
00368 std::vector<int> state_;
00370 std::vector<int> source_;
00372 std::vector<int> ffn_;
00374 std::vector<int> sfn_;
00376 std::vector<int> part_;
00378 std::vector<int> fringe_queue_;
00379
00381 bool is_current_free_;
00383 int current_index_;
00385 bool prev_is_ffn_;
00387 bool prev_is_sfn_;
00389 bool next_is_ffn_;
00391 bool next_is_sfn_;
00393 bool changed_1st_fn_;
00395 bool changed_2nd_fn_;
00397 int new2boundary_;
00398
00402 bool already_connected_;
00403
00405 Eigen::Vector3f proj_qp_;
00407 Eigen::Vector3f u_;
00409 Eigen::Vector3f v_;
00411 Eigen::Vector2f uvn_ffn_;
00413 Eigen::Vector2f uvn_sfn_;
00415 Eigen::Vector2f uvn_next_ffn_;
00417 Eigen::Vector2f uvn_next_sfn_;
00418
00420 Eigen::Vector3f tmp_;
00421
00425 void
00426 performReconstruction (pcl::PolygonMesh &output);
00427
00431 void
00432 performReconstruction (std::vector<pcl::Vertices> &polygons);
00433
00437 bool
00438 reconstructPolygons (std::vector<pcl::Vertices> &polygons);
00439
00441 std::string
00442 getClassName () const { return ("GreedyProjectionTriangulation"); }
00443
00454 void
00455 connectPoint (std::vector<pcl::Vertices> &polygons,
00456 const int prev_index,
00457 const int next_index,
00458 const int next_next_index,
00459 const Eigen::Vector2f &uvn_current,
00460 const Eigen::Vector2f &uvn_prev,
00461 const Eigen::Vector2f &uvn_next);
00462
00467 void
00468 closeTriangle (std::vector<pcl::Vertices> &polygons);
00469
00473 std::vector<std::vector<size_t> >
00474 getTriangleList (const pcl::PolygonMesh &input);
00475
00482 inline void
00483 addTriangle (int a, int b, int c, std::vector<pcl::Vertices> &polygons)
00484 {
00485 triangle_.vertices.resize (3);
00486 if (consistent_ordering_)
00487 {
00488 const PointInT p = input_->at (indices_->at (a));
00489 const Eigen::Vector3f pv = p.getVector3fMap ();
00490 if (p.getNormalVector3fMap ().dot (
00491 (pv - input_->at (indices_->at (b)).getVector3fMap ()).cross (
00492 pv - input_->at (indices_->at (c)).getVector3fMap ()) ) > 0)
00493 {
00494 triangle_.vertices[0] = a;
00495 triangle_.vertices[1] = b;
00496 triangle_.vertices[2] = c;
00497 }
00498 else
00499 {
00500 triangle_.vertices[0] = a;
00501 triangle_.vertices[1] = c;
00502 triangle_.vertices[2] = b;
00503 }
00504 }
00505 else
00506 {
00507 triangle_.vertices[0] = a;
00508 triangle_.vertices[1] = b;
00509 triangle_.vertices[2] = c;
00510 }
00511 polygons.push_back (triangle_);
00512 }
00513
00518 inline void
00519 addFringePoint (int v, int s)
00520 {
00521 source_[v] = s;
00522 part_[v] = part_[s];
00523 fringe_queue_.push_back(v);
00524 }
00525
00531 static inline bool
00532 nnAngleSortAsc (const nnAngle& a1, const nnAngle& a2)
00533 {
00534 if (a1.visible == a2.visible)
00535 return (a1.angle < a2.angle);
00536 else
00537 return a1.visible;
00538 }
00539 };
00540
00541 }
00542
00543 #ifdef PCL_NO_PRECOMPILE
00544 #include <pcl/surface/impl/gp3.hpp>
00545 #endif
00546
00547 #endif //#ifndef PCL_GP3_H_
00548