00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <cassert>
00019 #include <iomanip>
00020 #include <new>
00021 #include <vector>
00022 #include <stdexcept>
00023 #include "myrlog.h"
00024 #include "pbedefs.h"
00025 #include "tetmesh.h"
00026
00027 namespace mesh {
00028
00029 using namespace std;
00030
00031 TetMesh* TetMesh::instance_ = 0;
00032
00033 TetMesh::TetMesh()
00034 : _nofTet(0),
00035 _nofPoint(0),
00036 _nofEdge(0),
00037 _nofFace(0),
00038 _nofSym(0),
00039 _tetCounter(0),
00040 _octree(0)
00041 {
00042 assert(instance_ == 0);
00043 instance_ = this;
00044 }
00045
00046 TetMesh::~TetMesh() {
00047
00048 if (_octree)
00049 delete _octree;
00050 instance_ = 0;
00051 }
00052
00053
00054 void TetMesh::load_materials(const char* fileName){
00055 _materials = new Materials(fileName);
00056 }
00057
00058 Materials* TetMesh::get_materials() const{
00059 return _materials;
00060 }
00061
00062
00063 void TetMesh::initPoint(int nofPoint) {
00064 _nofPoint = nofPoint;
00065 _points.reserve(nofPoint);
00066 }
00067
00068 void TetMesh::initTet(int nofTet) {
00069 _nofTet = nofTet;
00070 _tets.reserve(nofTet);
00071 }
00072
00073 void TetMesh::insertPoint(int id, double x, double y, double z) {
00074 assert(static_cast<size_t>(id) == _points.size());
00075 _points.push_back(Point(id, x, y, z));
00076 }
00077
00078 void TetMesh::insertTet(id_t global_id, id_t id0, id_t id1, id_t id2, id_t id3, id_t material) {
00079
00080 id_t id = _tetCounter ++;
00081 id_t corners[4] = {id0, id1, id2, id3};
00082 assert(id == _tets.size());
00083 _tets.push_back(Tet(*this, id, corners, material));
00084 }
00085
00086 void TetMesh::generateEdges() {
00087 const int edgeNodeLocal[6][2] = {{0, 1}, {0, 2}, {0, 3},
00088 {1, 2}, {1, 3}, {2, 3}};
00089 id_t node0_id;
00090 id_t node1_id;
00091 id_t edge_id;
00092
00093 for (tet_iterator iter = tet_begin(); iter != tet_end(); ++ iter) {
00094 for (int j = 0; j < 6; j ++) {
00095 node0_id = (*iter).get_corner_id(edgeNodeLocal[j][0]);
00096 node1_id = (*iter).get_corner_id(edgeNodeLocal[j][1]);
00097 edge_id = insertEdge(node0_id, node1_id);
00098 (*iter).set_edge_id(j, edge_id);
00099
00100 (*iter).set_edge_orientation(j, get_edge(edge_id)->get_start_id() == node0_id);
00101 }
00102 }
00103 }
00104
00105 void TetMesh::generateFaces() {
00106 int node0, node1, node2;
00107 for (tet_iterator iter = tet_begin(); iter != tet_end(); ++ iter) {
00108 for (int j = 0; j < 4; j ++) {
00109 Tet::get_face_point_lids(j, node0, node1, node2);
00110 id_t face_id = insertFace((*iter).get_id(),
00111 (*iter).get_corner_id(node0),
00112 (*iter).get_corner_id(node1),
00113 (*iter).get_corner_id(node2));
00114 (*iter).set_face_id(j, face_id);
00115 }
00116 }
00117
00118 }
00119
00120 id_t TetMesh::insertEdge(id_t node0, id_t node1) {
00121 if (node0 > node1)
00122 std::swap<id_t>(node0, node1);
00123 EdgeMapKey key(node0, node1);
00124 EdgeMap::iterator iter = _edgeMap.find(key);
00125 if (iter == _edgeMap.end()) {
00126 _edges.push_back(Edge(_nofEdge, node0, node1));
00127 id_t edge = _nofEdge;
00128 _edgeMap[key] = edge;
00129 _nofEdge += 1;
00130 return edge;
00131 } else
00132 return (*iter).second;
00133 }
00134
00135 id_t TetMesh::insertFace(id_t tet, id_t node0, id_t node1, id_t node2) {
00136
00137 if (node0 > node1)
00138 std::swap<id_t>(node0, node1);
00139 if (node1 > node2)
00140 std::swap<id_t>(node1, node2);
00141 if (node0 > node1)
00142 std::swap<id_t>(node0, node1);
00143
00144
00145 FaceMapKey key(node0, node1, node2);
00146
00147 FaceMap::iterator iter = _faceMap.find(key);
00148
00149
00150
00151 if (iter == _faceMap.end()) {
00152
00153 _faces.push_back(Face(_nofFace, node0, node1, node2, tet));
00154 _faceMap[key] = _nofFace;
00155 return _nofFace ++;
00156 } else {
00157
00158 id_t face_id = (*iter).second;
00159 get_face(face_id)->set_tet_id(tet);
00160
00161 return face_id;
00162 }
00163 }
00164
00165 id_t TetMesh::lookupEdge(id_t node0, id_t node1) {
00166 if (node0 > node1)
00167 std::swap<id_t>(node0, node1);
00168
00169 EdgeMap::iterator iter = _edgeMap.find(EdgeMapKey(node0, node1));
00170 if (iter == _edgeMap.end())
00171 throw std::runtime_error("Accessed non-existing edge.");
00172 return (*iter).second;
00173 }
00174
00175 id_t TetMesh::lookupFace(id_t node0, id_t node1, id_t node2) {
00176
00177 if (node0 > node1)
00178 std::swap<id_t>(node0, node1);
00179 if (node1 > node2)
00180 std::swap<id_t>(node1, node2);
00181 if (node0 > node1)
00182 std::swap<id_t>(node0, node1);
00183
00184 FaceMap::iterator iter = _faceMap.find(FaceMapKey(node0, node1, node2));
00185 if (iter == _faceMap.end())
00186 throw std::runtime_error("Accessed non-existing face.");
00187 return (*iter).second;
00188 }
00189
00190 void TetMesh::dump_face_map(ostream& os) {
00191 os << "face map dump:" << endl;
00192 FaceMap::iterator it(_faceMap.begin());
00193 for (; it != _faceMap.end(); ++ it) {
00194 os << (*it).first.first << ", " <<
00195 (*it).first.second << ", " <<
00196 (*it).first.third << ": " <<
00197 (*it).second <<
00198 endl;
00199 }
00200 }
00201
00202 void TetMesh::setBoundaryOnFace(id_t face_id) {
00203 Face* face = get_face(face_id);
00204 id_t corners[3] = { face->get_corner_id(0),
00205 face->get_corner_id(1),
00206 face->get_corner_id(2) };
00207 face->set_boundary(true);
00208
00209 for (int i = 0; i < 3; i ++)
00210 get_point(corners[i])->set_boundary(true);
00211
00212 get_edge(lookupEdge(corners[0], corners[1]))->set_boundary(true);
00213 get_edge(lookupEdge(corners[0], corners[2]))->set_boundary(true);
00214 get_edge(lookupEdge(corners[1], corners[2]))->set_boundary(true);
00215 }
00216
00217 void TetMesh::setSymmetryPlaneOnFace(id_t face_id, int sym_id) {
00218 Face* face = get_face(face_id);
00219 id_t corners[3] = { face->get_corner_id(0),
00220 face->get_corner_id(1),
00221 face->get_corner_id(2) };
00222 face->set_symmetry_plane(sym_id);
00223
00224 for (int i = 0; i < 3; i ++)
00225 get_point(corners[i])->set_symmetry_plane(sym_id);
00226
00227 get_edge(lookupEdge(corners[0], corners[1]))->set_symmetry_plane(sym_id);
00228 get_edge(lookupEdge(corners[0], corners[2]))->set_symmetry_plane(sym_id);
00229 get_edge(lookupEdge(corners[1], corners[2]))->set_symmetry_plane(sym_id);
00230 }
00231
00232 void TetMesh::finalize_mesh(int nofSym) {
00233 _nofSym = nofSym;
00234
00235
00236
00237 _edgeMap.clear();
00238 _faceMap.clear();
00239 }
00240
00241 Tet* TetMesh::get_tet(id_t id) const {
00242 return const_cast<Tet *>(&_tets[id]);
00243 }
00244
00245 Face* TetMesh::get_face(id_t id) const {
00246 return const_cast<Face *>(&_faces[id]);
00247 }
00248
00249 Edge* TetMesh::get_edge(id_t id) const {
00250 return const_cast<Edge *>(&_edges[id]);
00251 }
00252
00253 Point* TetMesh::get_point(id_t id) const {
00254 return const_cast<Point *>(&_points[id]);
00255 }
00256
00257 void TetMesh::log_mesh_info() {
00258
00259 unsigned long size = _nofTet * sizeof(Tet) * 11 / 10;
00260 size += _nofFace * sizeof(Face) * 11 / 10;
00261 size += _nofEdge * sizeof(Edge) * 11 / 10;
00262 size += _nofPoint * sizeof(Point) * 11 / 10;
00263
00264 size += _nofEdge * sizeof(EdgeMapKey) + sizeof(id_t) * 11 / 10;
00265 size += _nofFace * sizeof(FaceMapKey) + sizeof(id_t) * 11 / 10;
00266 rInfo("Mesh stats: #tets=%d, #faces=%d, #edges=%d, #nodes=%d, #symplanes=%d, mem=%s",
00267 _nofTet, _nofFace, _nofEdge, _nofPoint, _nofSym, rlog::bytes2str(size).c_str());
00268 rDebug("sizeof(Tet)=%d, sizeof(Face)=%d, sizeof(Edge)=%d, sizeof(Point)=%d",
00269 static_cast<int>(sizeof(Tet)),
00270 static_cast<int>(sizeof(Face)),
00271 static_cast<int>(sizeof(Edge)),
00272 static_cast<int>(sizeof(Point)));
00273 }
00274
00275 void TetMesh::get_bounding_box(Vector3& center, Vector3& extent) const {
00276 Vector3 min, max, coord;
00277
00278 Point* point = get_point(0);
00279 min = point->get_coord();
00280 max = min;
00281 for (id_t i = 1; i < get_nof_points(); i ++) {
00282 coord = get_point(i)->get_coord();
00283 min.make_floor(coord);
00284 max.make_ceil(coord);
00285 }
00286 center = max.mid_point(min);
00287 extent = 0.5 * (max - min);
00288 }
00289
00290 void TetMesh::construct_octree() {
00291 rAssert(_octree == 0);
00292
00293
00294 Vector3 center, extent;
00295 get_bounding_box(center, extent);
00296
00297
00298 double length = extent.x;
00299 if (extent.y > length)
00300 length = extent.y;
00301 if (extent.z > length)
00302 length = extent.z;
00303
00304
00305 _octree = new LooseOctree<Tet>(center, length, 100);
00306
00307
00308 for (id_t t = 0; t < get_nof_tets(); t ++) {
00309 _octree->add_node(get_tet(t));
00310 }
00311 int max_depth, nof_octants, nof_nodes;
00312 double avg_node_depth;
00313 _octree->get_statistics(max_depth, avg_node_depth, nof_octants, nof_nodes);
00314 rInfo("Octree stats: max. depth=%d, #octants=%d, #nodes=%d, avg. #node per octant=%.2f, avg. node depth=%.2f",
00315 max_depth, nof_octants, nof_nodes, static_cast<double>(nof_nodes)/nof_octants, avg_node_depth);
00316
00317 #if 0
00318
00319
00320
00321 Vector3 p (0.1, 0.0, 2.6);
00322 std::vector<OctreeNode *> nodes;
00323 int nof_visited;
00324
00325 cout << "Finding tets containing " << p << "\n\n";
00326
00327 tet_iterator tet_it;
00328 cout << "Exhausive search yields (is_inside_bounding_box_gracious)\n";
00329 for (tet_it = tet_begin(); tet_it != tet_end(); ++ tet_it) {
00330 Tet* tet = *tet_it;
00331 if (tet->is_inside_bounding_box_gracious(p)) {
00332 std::cout << "inside tet " << tet->get_id() << "\n";
00333 for (int i = 0; i < 4; i ++) {
00334 cout << " " << tet->get_corner(i)->get_coord() << "\n";
00335 }
00336 }
00337 }
00338
00339 cout << "Exhausive search yields (is_inside_bounding_box)\n";
00340 for (tet_it = tet_begin(); tet_it != tet_end(); ++ tet_it) {
00341 Tet* tet = *tet_it;
00342 if (tet->is_inside_bounding_box(p)) {
00343 std::cout << "inside tet " << tet->get_id() << "\n";
00344 for (int i = 0; i < 4; i ++) {
00345 cout << " " << tet->get_corner(i)->get_coord() << "\n";
00346 }
00347 }
00348 }
00349
00350 cout << "Exhausive search yields (is_inside)\n";
00351 for (tet_it = tet_begin(); tet_it != tet_end(); ++ tet_it) {
00352 Tet* tet = *tet_it;
00353 if (tet->is_inside(p)) {
00354 std::cout << "inside tet " << tet->get_id() << "\n";
00355 for (int i = 0; i < 4; i ++) {
00356 cout << " " << tet->get_corner(i)->get_coord() << "\n";
00357 }
00358 }
00359 }
00360
00361 cout << "\nOctree: is_inside_bounding_box\n";
00362 nof_visited = 0; nodes.resize(0);
00363 _octree->find_nodes_by_point(p, nodes, nof_visited,
00364 (&OctreeNode::is_inside_bounding_box));
00365 std::cout << "nof. nodes visited=" << nof_visited << "\n";
00366 std::cout << "nof. nodes found=" << nodes.size() << "\n";
00367 std::vector<OctreeNode *>::iterator it;
00368 for (it = nodes.begin(); it != nodes.end(); it ++) {
00369 Tet *tet = dynamic_cast<Tet*>(*it);
00370 if (tet->is_inside(p)) {
00371 std::cout << "inside tet " << tet->get_id() << "\n";
00372 for (int i = 0; i < 4; i ++) {
00373 cout << " " << tet->get_corner(i)->get_coord() << "\n";
00374 }
00375 }
00376 }
00377
00378 cout << "\nOctree: is_inside_bounding_box_gracious\n";
00379 nof_visited = 0; nodes.resize(0);
00380 _octree->find_nodes_by_point(p, nodes, nof_visited,
00381 (&OctreeNode::is_inside_bounding_box_gracious));
00382 std::cout << "nof. nodes visited=" << nof_visited << "\n";
00383 std::cout << "nof. nodes found=" << nodes.size() << "\n";
00384 for (it = nodes.begin(); it != nodes.end(); it ++) {
00385 Tet *tet = dynamic_cast<Tet*>(*it);
00386 if (tet->is_inside(p)) {
00387 std::cout << "inside tet " << tet->get_id() << "\n";
00388 for (int i = 0; i < 4; i ++) {
00389 cout << " " << tet->get_corner(i)->get_coord() << "\n";
00390 }
00391 }
00392 }
00393
00394 cout << "\nOctree: Tet::is_inside\n";
00395 nof_visited = 0; nodes.resize(0);
00396 _octree->find_nodes_by_point(p, nodes, nof_visited,
00397 (LooseOctree::filter)(&Tet::is_inside));
00398 std::cout << "nof. nodes visited=" << nof_visited << "\n";
00399 std::cout << "nof. nodes found=" << nodes.size() << "\n";
00400 for (it = nodes.begin(); it != nodes.end(); it ++) {
00401 Tet *tet = dynamic_cast<Tet*>(*it);
00402 if (tet->is_inside(p)) {
00403 std::cout << "inside tet " << tet->get_id() << "\n";
00404 for (int i = 0; i < 4; i ++) {
00405 cout << " " << tet->get_corner(i)->get_coord() << "\n";
00406 }
00407 }
00408 }
00409
00410 cout << "\nOctree, find_one: Tet::is_inside\n";
00411 nof_visited = 0;
00412
00413
00414 OctreeNode* node = _octree->find_one_node_by_point(p, nof_visited, (LooseOctree::filter)(&Tet::is_inside));
00415 std::cout << "nof. nodes visited=" << nof_visited << "\n";
00416 if (node) {
00417 std::cout << "nof. nodes found=" << 1 << "\n";
00418 Vector4 p_simplex;
00419 dynamic_cast<Tet *>(node)->cartesian_to_simplex(p, p_simplex);
00420 cout << "is_inside(p) is " << dynamic_cast<Tet *>(node)->is_inside(p) << "\n";
00421 std::cout << "inside tet " << dynamic_cast<Tet *>(node)->get_id() << "\n";
00422 for (int i = 0; i < 4; i ++) {
00423 cout << " " << dynamic_cast<Tet*>(node)->get_corner(i)->get_coord() << "\n";
00424 }
00425 cout << "p_simplex=" << p_simplex << "\n";
00426 }
00427
00428 {
00429 Vector3 center, extent;
00430 get_tet(6488)->get_bounding_box(center, extent);
00431 cout.precision(17);
00432 cout << "\n\ncenter: " << center << "\nextent: " << extent << "\n";
00433 center -= p;
00434 center.x = fabs(center.x);
00435 center.y = fabs(center.y);
00436 center.z = fabs(center.z);
00437 cout << "|c-p|: " << center
00438 << "\nextend - |c-p|:" << extent - center
00439 << "\nextend_ - |c-p|:" << extent*(1+1e-13) - center
00440 << "\nbool: " << (center <= extent) << "\n";
00441 _octree->add_node(get_tet(6488))->dump(cout);
00442 cout << "eps_mach=" << std::numeric_limits<double>::epsilon() << "\n";
00443 }
00444 #endif
00445 }
00446
00447 void TetMesh::find_tets_by_point(const Vector3& p, vector<Tet *>& tets) const {
00448 assert(_octree);
00449
00450 pbe_start(132, "Octree traversal");
00451
00452
00453 std::vector<Tet*> nodes;
00454 int nof_visited = 0;
00455 _octree->find_nodes_by_point(p, nodes, nof_visited, &Tet::is_inside_bounding_box_gracious);
00456
00457
00458 tets.resize(0);
00459 std::vector<Tet*>::iterator it;
00460 for (it = nodes.begin(); it != nodes.end(); ++ it) {
00461 if ((*it)->is_inside_gracious(p))
00462 tets.push_back(*it);
00463 }
00464
00465 pbe_stop(132);
00466
00467 }
00468
00469 }