00001
00002 #include "imesh_operations.h"
00003
00004
00005
00006 #include <vgl/vgl_plane_3d.h>
00007 #include <vgl/vgl_area.h>
00008 #include <vgl/vgl_polygon.h>
00009 #include <vgl/vgl_triangle_test.h>
00010 #include <vnl/vnl_matrix.h>
00011 #include <vnl/vnl_double_3.h>
00012 #include <vnl/algo/vnl_svd.h>
00013 #include <vcl_cassert.h>
00014 #include <vcl_list.h>
00015
00016 #include <vcl_iostream.h>
00017
00018
00019
00020 imesh_mesh dual_mesh_with_normals(const imesh_mesh& mesh,
00021 const imesh_vertex_array_base& old_verts,
00022 double tau)
00023 {
00024 assert(mesh.has_half_edges());
00025 const imesh_half_edge_set& half_edges = mesh.half_edges();
00026 const imesh_vertex_array<3>& init_verts =
00027 static_cast<const imesh_vertex_array<3>&>(old_verts);
00028 const unsigned int num_verts = mesh.num_verts();
00029 const unsigned int num_faces = mesh.num_faces();
00030
00031 vcl_auto_ptr<imesh_face_array> new_faces(new imesh_face_array);
00032 vcl_auto_ptr<imesh_vertex_array<3> > new_verts(new imesh_vertex_array<3>);
00033
00034 for (unsigned int i=0; i<num_verts; ++i)
00035 {
00036 typedef imesh_half_edge_set::v_const_iterator vitr;
00037 vcl_vector<unsigned int> face;
00038 vitr end = half_edges.vertex_begin(i), v = end;
00039 face.push_back(v->face_index());
00040 for (++v; v != end; ++v)
00041 {
00042 face.push_back(v->face_index());
00043 }
00044 new_faces->push_back(face);
00045 }
00046 new_faces->set_normals(mesh.vertices().normals());
00047
00048
00049 for (unsigned int i=0; i<num_faces; ++i)
00050 {
00051 const unsigned int num_planes = mesh.faces().num_verts(i);
00052 vgl_point_3d<double> p0(init_verts[i]);
00053 vgl_vector_3d<double> v0(p0.x(), p0.y(), p0.z());
00054 vnl_matrix<double> A(num_planes, 3);
00055 vnl_vector<double> b(num_planes);
00056 for (unsigned int j=0; j<num_planes; ++j)
00057 {
00058 unsigned int v = mesh.faces()(i,j);
00059 vgl_point_3d<double> c(mesh.vertices<3>()[v]);
00060 c -= v0;
00061 vgl_plane_3d<double> p(mesh.vertices().normal(v), c);
00062 A(j,0) = p.nx();
00063 A(j,1) = p.ny();
00064 A(j,2) = p.nz();
00065 b(j) = -p.d();
00066 }
00067
00068 vnl_svd<double> svd(A);
00069 svd.zero_out_relative(tau);
00070 vgl_point_3d<double> p1(svd.solve(b).begin());
00071 p1 += v0;
00072 new_verts->push_back(p1);
00073 }
00074
00075 vcl_auto_ptr<imesh_face_array_base> nf(new_faces);
00076 vcl_auto_ptr<imesh_vertex_array_base > nv(new_verts);
00077 return imesh_mesh(nv,nf);
00078 }
00079
00080
00081
00082 void imesh_triangulate_face(const vcl_vector<vgl_point_2d<double> >& face_v,
00083 const vcl_vector<unsigned int>& face_i,
00084 imesh_regular_face_array<3>& tris)
00085 {
00086 const unsigned int numv = face_v.size();
00087 bool ccw = vgl_area_signed(vgl_polygon<double>(face_v)) > 0;
00088 vcl_vector<bool> concave_vert(numv,false);
00089 vcl_list<unsigned int> remain;
00090
00091 for (unsigned int i1=numv-2, i2=numv-1, i3=0; i3<numv; i1=i2, i2=i3++)
00092 {
00093 concave_vert[i2] = ccw != (signed_angle(face_v[i2]-face_v[i1],
00094 face_v[i3]-face_v[i2]) > 0);
00095 remain.push_back(i3);
00096 }
00097
00098 typedef vcl_list<unsigned int>::iterator ritr;
00099 unsigned int remain_size = 0;
00100 while (remain.size() > 2 && remain_size != remain.size()) {
00101 remain_size = remain.size();
00102 ritr curr = remain.end(), prev = --curr;
00103 --prev;
00104 for (ritr next=remain.begin(); next!=remain.end(); prev=curr, curr=next++)
00105 {
00106 if (concave_vert[*curr])
00107 continue;
00108
00109
00110 bool inside = false;
00111 for (ritr itr=remain.begin(); itr!=remain.end(); ++itr)
00112 {
00113 if (!concave_vert[*itr] || itr==curr || itr==prev || itr==next)
00114 continue;
00115 inside = vgl_triangle_test_inside(face_v[*prev].x(),face_v[*prev].y(),
00116 face_v[*curr].x(),face_v[*curr].y(),
00117 face_v[*next].x(),face_v[*next].y(),
00118 face_v[*itr ].x(),face_v[*itr ].y());
00119 if (inside)
00120 break;
00121 }
00122 if (inside)
00123 continue;
00124
00125
00126 tris.push_back(imesh_tri(face_i[*prev],face_i[*curr],face_i[*next]));
00127 remain.erase(curr);
00128 if (remain.size() < 3)
00129 break;
00130
00131
00132 ritr pprev = prev;
00133 if (pprev == remain.begin())
00134 pprev = remain.end();
00135 --pprev;
00136 ritr nnext = next;
00137 ++nnext;
00138 if (nnext == remain.end())
00139 nnext = remain.begin();
00140
00141 vgl_vector_2d<double> v1 = face_v[*prev]-face_v[*pprev];
00142 vgl_vector_2d<double> v2 = face_v[*next]-face_v[*prev];
00143 vgl_vector_2d<double> v3 = face_v[*nnext]-face_v[*next];
00144 concave_vert[*prev] = ccw != (signed_angle(v1,v2) > 0);
00145 concave_vert[*next] = ccw != (signed_angle(v2,v3) > 0);
00146 curr = prev;
00147 prev = pprev;
00148 }
00149 }
00150
00151
00152 if (remain_size == remain.size())
00153 vcl_cout << "error: "<<remain.size()<<" vertices remaining and no more ears"<<vcl_endl;
00154 }
00155
00156
00157
00158
00159 void
00160 imesh_triangulate_nonconvex(imesh_mesh& mesh)
00161 {
00162 const imesh_face_array_base& faces = mesh.faces();
00163 assert(mesh.vertices().dim() == 3);
00164 const imesh_vertex_array<3>& verts = mesh.vertices<3>();
00165
00166 vcl_auto_ptr<imesh_face_array_base> tris_base(new imesh_regular_face_array<3>);
00167 imesh_regular_face_array<3>* tris =
00168 static_cast<imesh_regular_face_array<3>*> (tris_base.get());
00169 int group = -1;
00170 if (faces.has_groups())
00171 group = 0;
00172 for (unsigned int f=0; f<faces.size(); ++f) {
00173 const unsigned int numv = faces.num_verts(f);
00174 if (numv == 3)
00175 {
00176 tris->push_back(imesh_tri(faces(f,0),faces(f,1),faces(f,2)));
00177 continue;
00178 }
00179
00180
00181
00182 vnl_matrix<double> M(3,numv);
00183 vnl_vector<double> mean(3,0.0);
00184 for (unsigned i=0; i<numv; ++i)
00185 {
00186 const imesh_vertex<3>& v = verts[faces(f,i)];
00187 mean[0] += M(0,i) = v[0];
00188 mean[1] += M(1,i) = v[1];
00189 mean[2] += M(2,i) = v[2];
00190 }
00191 mean /= numv;
00192 for (unsigned i=0; i<numv; ++i)
00193 {
00194 M(0,i) -= mean[0];
00195 M(1,i) -= mean[1];
00196 M(2,i) -= mean[2];
00197 }
00198 vnl_svd<double> svd_M(M);
00199 vnl_matrix<double> P = svd_M.U().extract(3,2).transpose();
00200
00201 vcl_vector<vgl_point_2d<double> > face_v;
00202 vcl_vector<unsigned int> face_i;
00203 for (unsigned i=0; i<numv; ++i)
00204 {
00205 const imesh_vertex<3>& v = verts[faces(f,i)];
00206 vnl_vector<double> p3 = vnl_double_3(v[0],v[1],v[2])-mean;
00207 vnl_vector<double> p2 = P*p3;
00208 face_v.push_back(vgl_point_2d<double>(p2[0],p2[1]));
00209 face_i.push_back(faces(f,i));
00210 }
00211 imesh_triangulate_face(face_v, face_i, *tris);
00212 if (group >= 0 && f+1 >= faces.groups()[group].second) {
00213 tris->make_group(faces.groups()[group++].first);
00214 }
00215 }
00216
00217 mesh.set_faces(tris_base);
00218 }