Go to the documentation of this file.00001
00002 #include "imesh_operations.h"
00003
00004
00005
00006 #include <vcl_iostream.h>
00007 #include <vcl_map.h>
00008 #include <vcl_cassert.h>
00009 #include <vgl/vgl_point_2d.h>
00010 #include <vgl/vgl_point_3d.h>
00011 #include <vgl/vgl_vector_3d.h>
00012
00013
00014 vcl_auto_ptr<imesh_regular_face_array<3> >
00015 imesh_triangulate(const imesh_face_array_base& faces)
00016 {
00017 vcl_auto_ptr<imesh_regular_face_array<3> > tris(new imesh_regular_face_array<3>);
00018 int group = -1;
00019 if (faces.has_groups())
00020 group = 0;
00021 for (unsigned int f=0; f<faces.size(); ++f) {
00022 for (unsigned i=2; i<faces.num_verts(f); ++i)
00023 tris->push_back(imesh_tri(faces(f,0),faces(f,i-1),faces(f,i)));
00024 if (group >= 0 && f+1 >= faces.groups()[group].second) {
00025 tris->make_group(faces.groups()[group++].first);
00026 }
00027 }
00028 return tris;
00029 }
00030
00031
00032
00033 vcl_auto_ptr<imesh_regular_face_array<3> >
00034 imesh_triangulate(const imesh_regular_face_array<4>& faces)
00035 {
00036 vcl_auto_ptr<imesh_regular_face_array<3> > tris(new imesh_regular_face_array<3>);
00037 int group = -1;
00038 if (faces.has_groups())
00039 group = 0;
00040 for (unsigned int f=0; f<faces.size(); ++f) {
00041 const imesh_regular_face<4>& face = faces[f];
00042 tris->push_back(imesh_tri(face[0],face[1],face[2]));
00043 tris->push_back(imesh_tri(face[0],face[2],face[3]));
00044 if (group >= 0 && f+1 >= faces.groups()[group].second) {
00045 tris->make_group(faces.groups()[group++].first);
00046 }
00047 }
00048 return tris;
00049 }
00050
00051
00052
00053 void
00054 imesh_triangulate(imesh_mesh& mesh)
00055 {
00056 switch (mesh.faces().regularity())
00057 {
00058 case 3: break;
00059 case 4:
00060 {
00061 vcl_auto_ptr<imesh_face_array_base> tris(
00062 imesh_triangulate(static_cast<const imesh_regular_face_array<4>&>(mesh.faces())));
00063 mesh.set_faces(tris);
00064 break;
00065 }
00066 default:
00067 {
00068 vcl_auto_ptr<imesh_face_array_base> tris(imesh_triangulate(mesh.faces()));
00069 mesh.set_faces(tris);
00070 break;
00071 }
00072 }
00073 }
00074
00075
00076 namespace {
00077
00078 void average_verts_2(imesh_vertex_array_base& verts,
00079 const vcl_vector<vcl_vector<unsigned int> >& idx)
00080 {
00081 assert(dynamic_cast<imesh_vertex_array<2>*>(&verts));
00082 imesh_vertex_array<2>& verts2 = static_cast<imesh_vertex_array<2>&>(verts);
00083
00084 for (unsigned int i=0; i<idx.size(); ++i) {
00085 const vcl_vector<unsigned int>& new_idx = idx[i];
00086 imesh_vertex<2> new_v;
00087 for (unsigned int j=0; j<new_idx.size(); ++j) {
00088 const imesh_vertex<2>& v = verts2[new_idx[j]];
00089 new_v[0] += v[0];
00090 new_v[1] += v[1];
00091 }
00092 new_v[0] /= new_idx.size();
00093 new_v[1] /= new_idx.size();
00094 verts2.push_back(new_v);
00095 }
00096 }
00097
00098
00099 void average_verts_3(imesh_vertex_array_base& verts,
00100 const vcl_vector<vcl_vector<unsigned int> >& idx)
00101 {
00102 assert(dynamic_cast<imesh_vertex_array<3>*>(&verts));
00103 imesh_vertex_array<3>& verts3 = static_cast<imesh_vertex_array<3>&>(verts);
00104
00105 for (unsigned int i=0; i<idx.size(); ++i) {
00106 const vcl_vector<unsigned int>& new_idx = idx[i];
00107 imesh_vertex<3> new_v;
00108 for (unsigned int j=0; j<new_idx.size(); ++j) {
00109 const imesh_vertex<3>& v = verts3[new_idx[j]];
00110 new_v[0] += v[0];
00111 new_v[1] += v[1];
00112 new_v[2] += v[2];
00113 }
00114 new_v[0] /= new_idx.size();
00115 new_v[1] /= new_idx.size();
00116 new_v[2] /= new_idx.size();
00117 verts3.push_back(new_v);
00118 }
00119 }
00120
00121 };
00122
00123
00124
00125
00126
00127 void
00128 imesh_quad_subdivide(imesh_mesh& mesh)
00129 {
00130 bool had_edges = mesh.has_half_edges();
00131 if (!had_edges)
00132 mesh.build_edge_graph();
00133
00134 const imesh_face_array_base& faces = mesh.faces();
00135 imesh_vertex_array_base& verts = mesh.vertices();
00136 const imesh_half_edge_set& half_edges = mesh.half_edges();
00137
00138 const unsigned int num_o_verts = mesh.num_verts();
00139 const unsigned int num_e_verts = mesh.num_edges();
00140 const unsigned int num_f_verts = mesh.num_faces();
00141
00142
00143 vcl_vector<vcl_vector<unsigned int> > merge_idx;
00144
00145 for (unsigned int e=0; e<num_e_verts; ++e) {
00146 vcl_vector<unsigned int> new_e_vert;
00147 new_e_vert.push_back(half_edges[2*e].vert_index());
00148 new_e_vert.push_back(half_edges[2*e+1].vert_index());
00149 merge_idx.push_back(new_e_vert);
00150 }
00151
00152 for (unsigned int f=0; f<num_f_verts; ++f) {
00153 vcl_vector<unsigned int> new_f_vert;
00154 for (unsigned int i=0; i<faces.num_verts(f); ++i) {
00155 new_f_vert.push_back(faces(f,i));
00156 }
00157 merge_idx.push_back(new_f_vert);
00158 }
00159
00160
00161 switch (verts.dim()) {
00162 case 2:
00163 average_verts_2(verts,merge_idx);
00164 break;
00165 case 3:
00166 average_verts_3(verts,merge_idx);
00167 break;
00168 default:
00169 vcl_cerr << "can not handle vertices of dimension: "
00170 << verts.dim() << '\n';
00171 return;
00172 }
00173
00174 if (mesh.has_tex_coords() == imesh_mesh::TEX_COORD_ON_VERT) {
00175 vcl_vector<vgl_point_2d<double> > tex_coords(mesh.tex_coords());
00176 for (unsigned int i=0; i<merge_idx.size(); ++i) {
00177 const vcl_vector<unsigned int>& new_idx = merge_idx[i];
00178 vgl_point_2d<double> new_tc(0,0);
00179 for (unsigned int j=0; j<new_idx.size(); ++j) {
00180 const vgl_point_2d<double>& v = tex_coords[new_idx[j]];
00181 new_tc.x() += v.x();
00182 new_tc.y() += v.y();
00183 }
00184 new_tc.x() /= new_idx.size();
00185 new_tc.y() /= new_idx.size();
00186 tex_coords.push_back(new_tc);
00187 }
00188 mesh.set_tex_coords(tex_coords);
00189 }
00190
00191
00192 vcl_auto_ptr<imesh_regular_face_array<4> > new_faces(new imesh_regular_face_array<4>);
00193 vcl_vector<vgl_point_2d<double> > tex_coords;
00194 unsigned int f_vert_base = num_o_verts+num_e_verts;
00195 for (unsigned int he=0; he<half_edges.size(); ++he) {
00196 if (half_edges[he].is_boundary())
00197 continue;
00198 unsigned int next = half_edges[he].next_index();
00199 new_faces->push_back(imesh_quad(f_vert_base + half_edges[he].face_index(),
00200 num_o_verts + (he>>1),
00201 half_edges[next].vert_index(),
00202 num_o_verts + (next>>1) ) );
00203 if (mesh.has_tex_coords() == imesh_mesh::TEX_COORD_ON_CORNER) {
00204 vcl_cerr << "subdivision of texture coords per corner is not implemented\n";
00205 }
00206 }
00207 if (mesh.has_tex_coords() == imesh_mesh::TEX_COORD_ON_CORNER) {
00208 mesh.set_tex_coords(tex_coords);
00209 }
00210
00211
00212 mesh.set_faces(vcl_auto_ptr<imesh_face_array_base>(new_faces));
00213 mesh.remove_edge_graph();
00214 if (had_edges)
00215 mesh.build_edge_graph();
00216 }
00217
00218
00219
00220
00221
00222
00223 void
00224 imesh_quad_subdivide(imesh_mesh& mesh, const vcl_set<unsigned int>& sel_faces)
00225 {
00226 bool had_edges = mesh.has_half_edges();
00227 if (!had_edges)
00228 mesh.build_edge_graph();
00229
00230 const imesh_face_array_base& faces = mesh.faces();
00231 imesh_vertex_array_base& verts = mesh.vertices();
00232 const imesh_half_edge_set& half_edges = mesh.half_edges();
00233
00234 const unsigned int num_o_verts = mesh.num_verts();
00235 const unsigned int num_e = mesh.num_edges();
00236 const unsigned int num_f = mesh.num_faces();
00237
00238 vcl_map<unsigned int,unsigned int> edge_map, face_map;
00239
00240
00241 vcl_vector<vcl_vector<unsigned int> > merge_idx;
00242
00243 for (unsigned int e=0; e<num_e; ++e) {
00244 if (sel_faces.count(half_edges[2*e].face_index()) +
00245 sel_faces.count(half_edges[2*e+1].face_index()) > 0) {
00246 vcl_vector<unsigned int> new_e_vert;
00247 new_e_vert.push_back(half_edges[2*e].vert_index());
00248 new_e_vert.push_back(half_edges[2*e+1].vert_index());
00249 edge_map[e] = merge_idx.size() + num_o_verts;
00250 merge_idx.push_back(new_e_vert);
00251 }
00252 }
00253
00254 for (vcl_set<unsigned int>::const_iterator fi = sel_faces.begin();
00255 fi != sel_faces.end(); ++fi) {
00256 vcl_vector<unsigned int> new_f_vert;
00257 for (unsigned int i=0; i<faces.num_verts(*fi); ++i) {
00258 new_f_vert.push_back(faces(*fi,i));
00259 }
00260 face_map[*fi] = merge_idx.size() + num_o_verts;
00261 merge_idx.push_back(new_f_vert);
00262 }
00263
00264
00265 switch (verts.dim()) {
00266 case 2:
00267 average_verts_2(verts,merge_idx);
00268 break;
00269 case 3:
00270 average_verts_3(verts,merge_idx);
00271 break;
00272 default:
00273 vcl_cerr << "can not handle vertices of dimension: "
00274 << verts.dim() << '\n';
00275 return;
00276 }
00277
00278 if (mesh.has_tex_coords() == imesh_mesh::TEX_COORD_ON_VERT) {
00279 vcl_vector<vgl_point_2d<double> > tex_coords(mesh.tex_coords());
00280 for (unsigned int i=0; i<merge_idx.size(); ++i) {
00281 const vcl_vector<unsigned int>& new_idx = merge_idx[i];
00282 vgl_point_2d<double> new_tc(0,0);
00283 for (unsigned int j=0; j<new_idx.size(); ++j) {
00284 const vgl_point_2d<double>& v = tex_coords[new_idx[j]];
00285 new_tc.x() += v.x();
00286 new_tc.y() += v.y();
00287 }
00288 new_tc.x() /= new_idx.size();
00289 new_tc.y() /= new_idx.size();
00290 tex_coords.push_back(new_tc);
00291 }
00292 mesh.set_tex_coords(tex_coords);
00293 }
00294
00295
00296 typedef vcl_map<unsigned int,unsigned int>::const_iterator map_itr;
00297 typedef imesh_half_edge_set::f_const_iterator face_itr;
00298 vcl_auto_ptr<imesh_face_array> new_faces(new imesh_face_array);
00299 int group = -1;
00300 if (faces.has_groups())
00301 group = 0;
00302 for (unsigned int f=0; f<num_f; ++f)
00303 {
00304 map_itr i = face_map.find(f);
00305 if (i == face_map.end()){
00306 face_itr fei = half_edges.face_begin(f);
00307 face_itr end = fei;
00308 vcl_vector<unsigned int> new_face;
00309 do{
00310 new_face.push_back(fei->vert_index());
00311 map_itr i2 = edge_map.find(fei->edge_index());
00312 if (i2 != edge_map.end())
00313 new_face.push_back(i2->second);
00314 ++fei;
00315 } while (fei != end);
00316 new_faces->push_back(new_face);
00317 }
00318 else{
00319 face_itr fei = half_edges.face_begin(f);
00320 face_itr end = fei;
00321 do{
00322 face_itr next = fei;
00323 ++next;
00324 new_faces->push_back(imesh_quad(i->second,
00325 edge_map[fei->edge_index()],
00326 next->vert_index(),
00327 edge_map[next->edge_index()] ) );
00328 fei = next;
00329 } while (fei != end);
00330 }
00331 if (group >= 0 && f+1 >= faces.groups()[group].second) {
00332 new_faces->make_group(faces.groups()[group++].first);
00333 }
00334 }
00335
00336
00337 mesh.set_faces(vcl_auto_ptr<imesh_face_array_base>(new_faces));
00338 mesh.remove_edge_graph();
00339 if (had_edges)
00340 mesh.build_edge_graph();
00341 }
00342
00343
00344
00345 imesh_mesh
00346 imesh_submesh_from_faces(const imesh_mesh& mesh, const vcl_set<unsigned int>& sel_faces)
00347 {
00348 const imesh_vertex_array<3>& verts = mesh.vertices<3>();
00349
00350 vcl_auto_ptr<imesh_face_array> new_faces(new imesh_face_array);
00351 vcl_auto_ptr<imesh_vertex_array<3> > new_verts(new imesh_vertex_array<3>);
00352 vcl_vector<int> vert_map(mesh.num_verts(),-1);
00353
00354 unsigned int new_count = 0;
00355 vcl_vector<vgl_vector_3d<double> > fnormals;
00356 vcl_vector<vgl_vector_3d<double> > vnormals;
00357 vcl_vector<vgl_point_2d<double> > tex_coords;
00358 const vcl_vector<vcl_pair<vcl_string,unsigned int> >& groups = mesh.faces().groups();
00359 unsigned int group_idx = 0;
00360 for (vcl_set<unsigned int>::const_iterator fi=sel_faces.begin();
00361 fi!=sel_faces.end(); ++fi)
00362 {
00363 const unsigned int num_v = mesh.faces().num_verts(*fi);
00364 vcl_vector<unsigned int> new_face;
00365 for (unsigned int i=0; i<num_v; ++i) {
00366 unsigned int v = mesh.faces()(*fi,i);
00367 int& nv = vert_map[v];
00368 if (nv < 0) {
00369 nv = new_count++;
00370 new_verts->push_back(verts[v]);
00371 if (verts.has_normals())
00372 vnormals.push_back(verts.normal(v));
00373 if (mesh.has_tex_coords() == imesh_mesh::TEX_COORD_ON_VERT)
00374 tex_coords.push_back(mesh.tex_coords()[v]);
00375 }
00376 new_face.push_back(nv);
00377 }
00378 if (mesh.faces().has_groups()) {
00379 while (group_idx < groups.size() && groups[group_idx].second <= *fi)
00380 {
00381 new_faces->make_group(groups[group_idx].first);
00382 ++group_idx;
00383 }
00384 }
00385 new_faces->push_back(new_face);
00386 if (mesh.faces().has_normals())
00387 fnormals.push_back(mesh.faces().normal(*fi));
00388 }
00389 if (!fnormals.empty())
00390 new_faces->set_normals(fnormals);
00391 if (!vnormals.empty())
00392 new_verts->set_normals(vnormals);
00393
00394
00395 vcl_auto_ptr<imesh_vertex_array_base> nverts(new_verts);
00396 vcl_auto_ptr<imesh_face_array_base> nfaces(new_faces);
00397 imesh_mesh submesh(nverts,nfaces);
00398
00399 if (mesh.has_tex_coords())
00400 submesh.set_tex_coords(tex_coords);
00401
00402 return submesh;
00403 }
00404
00405
00406
00407 void imesh_flip_faces( imesh_mesh& mesh )
00408 {
00409 for (unsigned int f=0; f<mesh.num_faces(); ++f)
00410 {
00411 mesh.faces().flip_orientation(f);
00412 }
00413 }
00414
00415
00416
00417 void imesh_flip_faces( imesh_mesh& mesh, const vcl_set<unsigned int>& sel_faces)
00418 {
00419 for (vcl_set<unsigned int>::const_iterator fi=sel_faces.begin();
00420 fi!=sel_faces.end(); ++fi)
00421 {
00422 mesh.faces().flip_orientation(*fi);
00423 }
00424 }
00425
00426
00427
00428 imesh_mesh dual_mesh(const imesh_mesh& mesh)
00429 {
00430 assert(mesh.has_half_edges());
00431 const imesh_half_edge_set& half_edges = mesh.half_edges();
00432 const unsigned int num_verts = mesh.num_verts();
00433 const unsigned int num_faces = mesh.num_faces();
00434
00435 vcl_auto_ptr<imesh_face_array> new_faces(new imesh_face_array);
00436 vcl_auto_ptr<imesh_vertex_array<3> > new_verts(new imesh_vertex_array<3>);
00437
00438 for (unsigned int i=0; i<num_faces; ++i)
00439 {
00440 vcl_vector<vgl_point_3d<double> > pts;
00441 for (unsigned int j=0; j<mesh.faces().num_verts(i); ++j)
00442 {
00443 unsigned int v = mesh.faces()(i,j);
00444 pts.push_back(mesh.vertices<3>()[v]);
00445 }
00446 new_verts->push_back(centre(pts));
00447 }
00448 if (mesh.faces().has_normals())
00449 new_verts->set_normals(mesh.faces().normals());
00450
00451 for (unsigned int i=0; i<num_verts; ++i)
00452 {
00453 typedef imesh_half_edge_set::v_const_iterator vitr;
00454 vcl_vector<unsigned int> face;
00455 vitr end = half_edges.vertex_begin(i), v = end;
00456 face.push_back(v->face_index());
00457 for (++v; v != end; ++v)
00458 {
00459 face.push_back(v->face_index());
00460 }
00461 new_faces->push_back(face);
00462 }
00463 if (mesh.vertices().has_normals())
00464 new_faces->set_normals(mesh.vertices().normals());
00465
00466 vcl_auto_ptr<imesh_face_array_base> nf(new_faces);
00467 vcl_auto_ptr<imesh_vertex_array_base > nv(new_verts);
00468 return imesh_mesh(nv,nf);
00469 }
00470
00471
00472 bool contains_point(const imesh_mesh& mesh,vgl_point_3d<double> p)
00473 {
00474 vcl_auto_ptr<imesh_face_array> new_faces(new imesh_face_array);
00475 vcl_auto_ptr<imesh_vertex_array<3> > new_verts(new imesh_vertex_array<3>);
00476
00477 for (unsigned int i=0; i<mesh.num_faces(); ++i)
00478 {
00479 vcl_vector<vgl_point_3d<double> > pts;
00480 for (unsigned int j=0; j<mesh.faces().num_verts(i); ++j)
00481 {
00482 unsigned int v = mesh.faces()(i,j);
00483 pts.push_back(mesh.vertices<3>()[v]);
00484 }
00485 new_verts->push_back(centre(pts));
00486 }
00487 if (mesh.faces().has_normals())
00488 new_verts->set_normals(mesh.faces().normals());
00489 vcl_vector<vgl_vector_3d<double> > normals= new_verts->normals();
00490 imesh_vertex_array<3>::const_iterator iter=new_verts->begin();
00491 unsigned int i=0;
00492 for (;iter!=new_verts->end();iter++,i++)
00493 {
00494 vgl_point_3d<double> new_vert((*iter)[0],(*iter)[1],(*iter)[2]);
00495 double dotprod=dot_product<double>(new_vert-p,normals[i]);
00496 if (dotprod<0)
00497 return false;
00498 }
00499 return true;
00500 }