00001
00002 #ifndef imesh_imls_surface_h_
00003 #define imesh_imls_surface_h_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <imesh/imesh_mesh.h>
00021 #include <imesh/algo/imesh_kd_tree.h>
00022 #include <vnl/vnl_double_3x3.h>
00023
00024
00025 class imesh_imls_surface
00026 {
00027 public:
00028
00029 imesh_imls_surface(const imesh_mesh& mesh,
00030 double eps = 0.01, double lambda = 0.1,
00031 bool enforce_bounded = false,
00032 const vcl_set<unsigned int>& no_normal_faces = vcl_set<unsigned int>());
00033
00034
00035 imesh_imls_surface(const imesh_imls_surface& other);
00036
00037
00038 double operator() (const vgl_point_3d<double>& p) const;
00039
00040
00041 double operator() (double x, double y, double z) const
00042 {
00043 return (*this)(vgl_point_3d<double>(x,y,z));
00044 }
00045
00046
00047 double w2(double dist2) const
00048 {
00049 double w = 1.0 / (dist2 + eps2_);
00050 return w*w;
00051 }
00052
00053
00054 vgl_box_3d<double> bounding_box() const;
00055
00056
00057 double deriv(const vgl_point_3d<double>& p, vgl_vector_3d<double>& dp) const;
00058
00059
00060 double deriv2(const vgl_point_3d<double>& p, vgl_vector_3d<double>& dp,
00061 vnl_double_3x3& ddp) const;
00062
00063
00064 void set_epsilon(double eps);
00065
00066
00067 void set_lambda(double lambda) { lambda_ = lambda; }
00068
00069
00070 struct integral_data
00071 {
00072 integral_data()
00073 : I(0), I_phi(0), dI(0,0,0), dI_phi(0,0,0) {}
00074 integral_data(double i, double i_phi,
00075 const vgl_vector_3d<double>& di,
00076 const vgl_vector_3d<double>& di_phi)
00077 : I(i), I_phi(i_phi), dI(di), dI_phi(di_phi) {}
00078 integral_data operator+ (const integral_data& other) const
00079 {
00080 return integral_data(I+other.I, I_phi+other.I_phi,
00081 dI+other.dI, dI_phi+other.dI_phi);
00082 }
00083 integral_data& operator+= (const integral_data& other)
00084 {
00085 I += other.I; I_phi += other.I_phi;
00086 dI += other.dI; dI_phi += other.dI_phi;
00087 return *this;
00088 }
00089 integral_data& operator*= (const double& s)
00090 {
00091 I *= s; I_phi *= s;
00092 dI *= s; dI_phi *= s;
00093 return *this;
00094 }
00095
00096 double I, I_phi;
00097 vgl_vector_3d<double> dI, dI_phi;
00098 };
00099
00100
00101 static void line_integrals(double k1, double k2, double& I1, double& Ix);
00102
00103
00104
00105 static void line_integrals(double k1, double k2,
00106 double& I1, double& Ix,
00107 double& dI1, double& dIx, double& dIx2);
00108
00109
00110
00111
00112 static double line_integral(const vgl_point_3d<double>& x,
00113 const vgl_point_3d<double>& p0,
00114 const vgl_point_3d<double>& p1,
00115 double v0, double v1, double eps);
00116
00117
00118 static vgl_vector_3d<double>
00119 line_integral_deriv(const vgl_point_3d<double>& x,
00120 const vgl_point_3d<double>& p0,
00121 const vgl_point_3d<double>& p1,
00122 double v0, double v1, double eps2);
00123
00124
00125
00126
00127
00128
00129 static vgl_vector_2d<double>
00130 split_triangle_quadrature(const vgl_point_3d<double>& x,
00131 const vgl_point_3d<double>& m,
00132 const vgl_point_3d<double>& pp,
00133 const vgl_point_3d<double>& pm,
00134 double v0, double v1, double v2,
00135 double eps);
00136
00137
00138
00139 template <class T, class F>
00140 static T
00141 triangle_quadrature(F quad_func,
00142 const vgl_point_3d<double>& x,
00143 const vgl_point_3d<double>& p0,
00144 const vgl_point_3d<double>& p1,
00145 const vgl_point_3d<double>& p2,
00146 const vgl_vector_3d<double>& n,
00147 double v0, double v1, double v2,
00148 double eps);
00149
00150
00151
00152
00153
00154
00155
00156 static integral_data
00157 split_triangle_quadrature_with_deriv(const vgl_point_3d<double>& x,
00158 const vgl_point_3d<double>& m,
00159 const vgl_point_3d<double>& pp,
00160 const vgl_point_3d<double>& pm,
00161 double v0, double v1, double v2,
00162 double eps);
00163
00164 private:
00165
00166
00167 void compute_centroids_rec(const vcl_auto_ptr<imesh_kd_tree_node>& node,
00168 const vcl_set<unsigned int>& no_normal_faces);
00169
00170
00171 void compute_unweighed_rec(const vcl_auto_ptr<imesh_kd_tree_node>& node);
00172
00173
00174
00175 void compute_iso_level();
00176
00177
00178
00179 void compute_enclosing_phi();
00180
00181 vcl_vector<vgl_point_3d<double> > verts_;
00182 vcl_auto_ptr<imesh_regular_face_array<3> > triangles_;
00183
00184 vcl_auto_ptr<imesh_kd_tree_node> kd_tree_;
00185 vcl_vector<double> phi_;
00186 vcl_vector<double> area_;
00187 vcl_vector<double> unweighted_;
00188 vcl_vector<vgl_point_3d<double> > centroid_;
00189 vcl_vector<vgl_vector_3d<double> > normals_;
00190 vcl_vector<double> normal_len_;
00191
00192 double eps2_;
00193 double lambda_;
00194 double iso_level_;
00195 bool bounded_;
00196 };
00197
00198
00199
00200
00201 vgl_point_3d<double> bisect(const imesh_imls_surface& f,
00202 vgl_point_3d<double> pp, vgl_point_3d<double> pn,
00203 double feps = 1e-8, double xeps = 1e-16);
00204
00205
00206
00207
00208 bool snap_to_surface(const imesh_imls_surface& f,
00209 vgl_point_3d<double>& p,
00210 double step = 0.5, double eps = 1e-5);
00211
00212
00213
00214
00215 bool snap_to_surface_with_normal(const imesh_imls_surface& f,
00216 vgl_point_3d<double>& p,
00217 vgl_vector_3d<double> n,
00218 double step = 0.5, double eps = 1e-8);
00219
00220
00221
00222
00223 bool snap_to_surface(const imesh_imls_surface& f,
00224 vgl_vector_3d<double> dir,
00225 vgl_point_3d<double>& p,
00226 double step = 0.5, double eps = 1e-5);
00227
00228
00229 #endif // imesh_imls_surface_h_