Chi-Tech
chi_surfacemesh_loadexport.cc
Go to the documentation of this file.
1#include"chi_surfacemesh.h"
2
3#include<iostream>
4#include<fstream>
5#include <algorithm>
6
7#include "chi_runtime.h"
8#include "chi_log.h"
9
10
11//#########################################################
12/** Loads a surface mesh from a wavefront .obj file.*/
14 ImportFromOBJFile(const std::string& fileName, bool as_poly/*=false*/,
15 const chi_mesh::Vector3& transform/*={0,0,0}*/)
16{
17
18
19 //===================================================== Opening the file
20 std::ifstream file;
21 file.open(fileName);
22 if (!file.is_open())
23 {
25 << "Failed to open file: "<< fileName<<" in call "
26 << "to ImportFromOBJFile \n";
27 Chi::Exit(EXIT_FAILURE);
28 }
29 Chi::log.Log() << "Loading surface mesh with transform " << transform.PrintStr();
30
31 //===================================================== Reading every line and determining size
32 std::string file_line;
33 std::string delimiter = " ";
34 int counter=0;
35 while (std::getline(file,file_line))
36 {
37 counter++;
38
39 //===================================================== Get the first word
40 size_t beg_of_word = file_line.find_first_not_of(delimiter);
41 size_t end_of_word = file_line.find(delimiter,beg_of_word-beg_of_word);
42 std::string first_word = file_line.substr(beg_of_word,end_of_word);
43 std::string sub_word;
44
45 //===================================================== Keyword "v" for Vertex
46 if (first_word == "v")
47 {
48 chi_mesh::Vertex newVertex;
49 for (int k=1;k<=3;k++)
50 {
51 //================================== Extract sub word
52 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
53 end_of_word = file_line.find(delimiter, beg_of_word);
54 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
55
56 //============================= Convert word to number
57 try
58 {
59 double numValue = std::stod(sub_word);
60
61 if (k==1) newVertex.x = numValue + transform.x;
62 else if (k==2) newVertex.y = numValue + transform.y;
63 else if (k==3) newVertex.z = numValue + transform.z;
64 }
65
66 //============================= Catch conversion error
67 catch(const std::invalid_argument& ia)
68 {
69 std::cout<<"Exception caught!"<<std::endl;
70 }
71
72 //============================= Stop word extraction on line end
73 if (end_of_word==std::string::npos) {break;}
74 }
75 this->vertices_.push_back(newVertex);
76 }
77
78 //===================================================== Keyword "vt" for Vertex
79 if (first_word.compare("vt")==0) {
80 chi_mesh::Vertex newVertex;
81 for (int k=1;k<=2;k++)
82 {
83 //================================== Extract sub word
84 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
85 end_of_word = file_line.find(delimiter, beg_of_word);
86 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
87
88 //============================= Convert word to number
89 try{ double numValue = std::stod(sub_word);
90 //*newVertex->value[k-1] = numValue;
91 if (k==1)
92 {
93 newVertex.x = numValue;
94 }
95 else if (k==2)
96 {
97 newVertex.y = numValue;
98 }
99 else if (k==3)
100 {
101 newVertex.z = numValue;
102 }
103 }
104
105 //============================= Catch conversion error
106 catch(const std::invalid_argument& ia)
107 {
108 //*newVertex->value[k-1] = 0.0;
109 std::cout<<"Exception caught!"<<std::endl;
110 }
111
112 //============================= Stop word extraction on line end
113 if (end_of_word==std::string::npos) {break;}
114 }
115 this->tex_vertices_.push_back(newVertex);
116 }
117
118 //===================================================== Keyword "vn" for normal
119 if (first_word.compare("vn")==0) {
120 chi_mesh::Normal newNormal;
121 for (int k=1;k<=3;k++)
122 {
123 //================================== Extract sub word
124 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
125 end_of_word = file_line.find(delimiter, beg_of_word);
126 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
127
128 //============================= Convert word to number
129 try{ double numValue = std::stod(sub_word);
130 //*newNormal->value[k-1] = numValue;
131 if (k==1)
132 {
133 newNormal.x = numValue;
134 }
135 else if (k==2)
136 {
137 newNormal.y = numValue;
138 }
139 else if (k==3)
140 {
141 newNormal.z = numValue;
142 }
143 }
144
145 //============================= Catch conversion error
146 catch(const std::invalid_argument& ia)
147 {
148 //*newNormal->value[k-1] = 0.0;
149 std::cout<<"Exception caught!"<<std::endl;
150 }
151
152 //============================= Stop word extraction on line end
153 if (end_of_word==std::string::npos) {break;}
154 }
155 this->normals_.push_back(newNormal);
156 }
157
158 //===================================================== Keyword "f" for face
159 if (first_word.compare("f")==0)
160 {
161 int number_of_verts = std::count(file_line.begin(),file_line.end(),'/')/2;
162 if ((number_of_verts==3) && (!as_poly))
163 {
164 chi_mesh::Face* newFace = new chi_mesh::Face;
165
166 for (int k=1;k<=3;k++)
167 {
168 //================================== Extract sub word
169 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
170 end_of_word = file_line.find(delimiter, beg_of_word);
171 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
172
173 //============================= Extract locations of hiphens
174 size_t first_dash = sub_word.find("/");
175 size_t last_dash = sub_word.find_last_of("/");
176
177 //============================= Extract the words ass. w vertex and normal
178 std::string vert_word = sub_word.substr(0,first_dash-0);
179 std::string norm_word = sub_word.substr(last_dash+1,sub_word.length()-last_dash-1);
180
181 //============================= Convert word to number (Vertex)
182 try{ int numValue = std::stoi(vert_word);
183 newFace->v_index[k-1] = numValue-1;
184 }
185 catch(const std::invalid_argument& ia){std::cout<<"Exception caught!"<<std::endl; }
186
187 //============================= Convert word to number (Normal)
188 try{ int numValue = std::stoi(norm_word);
189 newFace->n_index[k-1] = numValue-1;
190 }
191 catch(const std::invalid_argument& ia){std::cout<<"Exception caught!"<<std::endl; }
192
193 //============================= Convert word to number (Texture Vertex)
194 if (last_dash>(first_dash+1)){
195 std::string tvert_word = sub_word.substr(first_dash+1,last_dash-first_dash-1);
196 try{ int numValue = std::stoi(tvert_word);
197 newFace->vt_index[k-1] = numValue-1;
198 }
199 catch(const std::invalid_argument& ia)
200 {
201 std::cout<<"Exception caught!"<<std::endl;
202 }
203 }
204
205 //============================= Stop word extraction on line end
206 if (end_of_word==std::string::npos) {break;}
207 }
208
209
210 //==================================== Set edges
211 newFace->e_index[0][0] = newFace->v_index[0];
212 newFace->e_index[0][1] = newFace->v_index[1];
213
214 newFace->e_index[1][0] = newFace->v_index[1];
215 newFace->e_index[1][1] = newFace->v_index[2];
216
217 newFace->e_index[2][0] = newFace->v_index[2];
218 newFace->e_index[2][1] = newFace->v_index[0];
219
220 this->faces_.push_back(*newFace);
221 }
222 else
223 {
225
226 for (int k=1;k<=number_of_verts;k++)
227 {
228 //================================== Extract sub word
229 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
230 end_of_word = file_line.find(delimiter, beg_of_word);
231 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
232
233 //============================= Extract locations of hiphens
234 size_t first_dash = sub_word.find("/");
235 size_t last_dash = sub_word.find_last_of("/");
236
237 //============================= Extract the words ass. w vertex and normal
238 std::string vert_word = sub_word.substr(0,first_dash-0);
239 std::string norm_word = sub_word.substr(last_dash+1,sub_word.length()-last_dash-1);
240
241 //============================= Convert word to number (Vertex)
242 try{ int numValue = std::stoi(vert_word);
243 newFace->v_indices.push_back(numValue-1);
244 }
245 catch(const std::invalid_argument& ia){std::cout<<"Exception caught!"<<std::endl; }
246
247 //============================= Convert word to number (Normal)
248 try{ int numValue = std::stoi(norm_word);
249 //newFace->n_indices.push_back(numValue-1);
250 }
251 catch(const std::invalid_argument& ia){std::cout<<"Exception caught!"<<std::endl; }
252
253 //============================= Convert word to number (Texture Vertex)
254 if (last_dash>(first_dash+1)){
255 std::string tvert_word = sub_word.substr(first_dash+1,last_dash-first_dash-1);
256 try{ int numValue = std::stoi(tvert_word);
257 //newFace->vt_indices.push_back(numValue-1);
258 }
259 catch(const std::invalid_argument& ia)
260 {
261 std::cout<<"Exception caught!"<<std::endl;
262 }
263 }
264
265 //============================= Stop word extraction on line end
266 if (end_of_word==std::string::npos) {break;}
267 }
268
269 for (int v=0;v<(newFace->v_indices.size());v++)
270 {
271 int* side_indices = new int[4];
272
273 side_indices[0] = newFace->v_indices[v];
274 side_indices[1] = newFace->v_indices[v+1];
275 side_indices[2] = -1;
276 side_indices[3] = -1;
277
278 if ((v+1)>=newFace->v_indices.size())
279 {
280 side_indices[1] = newFace->v_indices[0];
281 }
282
283 newFace->edges.push_back(side_indices);
284 }
285
286
287 this->poly_faces_.push_back(newFace);
288 }
289
290
291 }
292
293
294 //=================================================== Keyword "l" for line
295 if (first_word.compare("l")==0){
296 chi_mesh::Edge newEdge;
297
298 //================================== Extract sub word
299 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
300 end_of_word = file_line.find(delimiter, beg_of_word);
301 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
302
303 //================================== Convert to number
304 try{ int numValue = std::stoi(sub_word);
305 newEdge.v_index[0] = numValue-1;
306 }
307 catch(const std::invalid_argument& ia){std::cout<<"Exception caught!"<<std::endl; }
308
309 //================================== Extract sub word
310 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
311 end_of_word = file_line.find(delimiter, beg_of_word);
312 sub_word = file_line.substr(beg_of_word, end_of_word-beg_of_word);
313
314 //================================== Convert to number
315 try{ int numValue = std::stoi(sub_word);
316 newEdge.v_index[1] = numValue-1;
317 }
318 catch(const std::invalid_argument& ia){std::cout<<"Exception caught!"<<std::endl; }
319
320 newEdge.vertices[0] = this->vertices_.at(newEdge.v_index[0]);
321 newEdge.vertices[1] = this->vertices_.at(newEdge.v_index[1]);
322
323 this->lines_.push_back(newEdge);
324
325 //printf("line %d->%d\n",newEdge.v_index[0],newEdge.v_index[1]);
326 }
327
328 }
329 file.close();
330
331 //======================================================= Calculate face properties
332 std::vector<chi_mesh::Face>::iterator curFace;
333 for (curFace = this->faces_.begin(); curFace != this->faces_.end(); curFace++)
334 {
335 //=========================================== Calculate geometrical normal
336 chi_mesh::Vertex vA = this->vertices_.at(curFace->v_index[0]);
337 chi_mesh::Vertex vB = this->vertices_.at(curFace->v_index[1]);
338 chi_mesh::Vertex vC = this->vertices_.at(curFace->v_index[2]);
339
340 chi_mesh::Vector3 vAB = vB - vA;
341 chi_mesh::Vector3 vBC = vC - vB;
342
343 curFace->geometric_normal = vAB.Cross(vBC);
344 curFace->geometric_normal = curFace->geometric_normal/curFace->geometric_normal.Norm();
345
346 //=========================================== Calculate Assigned normal
347 chi_mesh::Vertex nA = this->normals_.at(curFace->n_index[0]);
348 chi_mesh::Vertex nB = this->normals_.at(curFace->n_index[1]);
349 chi_mesh::Vertex nC = this->normals_.at(curFace->n_index[2]);
350
351 chi_mesh::Vector3 nAvg = (nA + nB + nC) / 3.0;
352 nAvg = nAvg/nAvg.Norm();
353
354 curFace->assigned_normal = nAvg;
355
356 //=========================================== Compute face center
357 curFace->face_centroid = (vA+vB+vC)/3.0;
358 }
359 std::vector<chi_mesh::PolyFace*>::iterator curPFace;
360 for (curPFace = this->poly_faces_.begin();
361 curPFace!=this->poly_faces_.end();
362 curPFace++)
363 {
364 chi_mesh::Vector3 centroid;
365 int num_verts = (*curPFace)->v_indices.size();
366 for (int v=0; v<num_verts; v++)
367 centroid = centroid + vertices_[(*curPFace)->v_indices[v]];
368
369 centroid = centroid/num_verts;
370
371 (*curPFace)->face_centroid = centroid;
372
373 chi_mesh::Vector3 n = (vertices_[(*curPFace)->v_indices[1]] -
374 vertices_[(*curPFace)->v_indices[0]]).Cross(
375 centroid - vertices_[(*curPFace)->v_indices[1]]);
376 n = n/n.Norm();
377
378 (*curPFace)->geometric_normal = n;
379 }
380
382
383 //============================================= Check each vertex is accounted
384 Chi::log.Log()
385 << "Surface mesh loaded with "
386 << this->faces_.size() << " triangle faces and "
387 << this->poly_faces_.size() << " polygon faces.";
388 //chi::Exit(EXIT_FAILURE);
389
390 return 0;
391}
392
393//#########################################################
394/** Loads a surface mesh from triangle's file format.*/
396ImportFromTriangleFiles(const char* fileName, bool as_poly=false)
397{
398 std::string node_filename = std::string(fileName) +
399 std::string(".1.node");
400 std::string tria_filename = std::string(fileName) +
401 std::string(".1.ele");
402
403 //===================================================== Opening the node file
404 std::ifstream file;
405 file.open(node_filename);
406 if (!file.is_open())
407 {
409 << "Failed to open file: "<< node_filename <<" in call "
410 << "to ImportFromOBJFile \n";
411 Chi::Exit(EXIT_FAILURE);
412 }
413
414 int num_verts;
415 char line[250];
416 file >> num_verts;
417 file.getline(line,250);
418 for (int v=1; v<=num_verts; v++)
419 {
420 int vert_index;
421 chi_mesh::Vertex vertex;
422 file >> vert_index >> vertex.x >> vertex.y;
423 file.getline(line,250);
424
425 vertices_.push_back(vertex);
426 }
427
428 file.close();
429
430 //===================================================== Opening the ele file
431 file.open(tria_filename);
432 if (!file.is_open())
433 {
435 << "Failed to open file: "<< tria_filename <<" in call "
436 << "to ImportFromOBJFile \n";
437 Chi::Exit(EXIT_FAILURE);
438 }
439
440 int num_tris;
441
442 file >> num_tris;
443 file.getline(line,250);
444 for (int v=1; v<=num_tris; v++)
445 {
446 int tri_index;
448
449 int v0,v1,v2;
450 file >> tri_index >> v0 >> v1 >> v2;
451 file.getline(line,250);
452
453
454 newFace->v_indices.resize(3);
455 newFace->v_indices[0] = v0-1;
456 newFace->v_indices[1] = v1-1;
457 newFace->v_indices[2] = v2-1;
458
459 for (int e=0; e<3; e++)
460 {
461 int* side_indices = new int[4];
462
463 if (e<2)
464 {
465 side_indices[0] = newFace->v_indices[e];
466 side_indices[1] = newFace->v_indices[e+1];
467 side_indices[2] = -1;
468 side_indices[3] = -1;
469 }
470 else
471 {
472 side_indices[0] = newFace->v_indices[e];
473 side_indices[1] = newFace->v_indices[0];
474 side_indices[2] = -1;
475 side_indices[3] = -1;
476 }
477 newFace->edges.push_back(side_indices);
478 }
479
480 poly_faces_.push_back(newFace);
481 }
482
483 file.close();
484
485 //======================================================= Calculate face properties
486 std::vector<chi_mesh::Face>::iterator curFace;
487 for (curFace = this->faces_.begin(); curFace != this->faces_.end(); curFace++)
488 {
489 //=========================================== Calculate geometrical normal
490 chi_mesh::Vertex vA = this->vertices_.at(curFace->v_index[0]);
491 chi_mesh::Vertex vB = this->vertices_.at(curFace->v_index[1]);
492 chi_mesh::Vertex vC = this->vertices_.at(curFace->v_index[2]);
493
494 chi_mesh::Vector3 vAB = vB - vA;
495 chi_mesh::Vector3 vBC = vC - vB;
496
497 curFace->geometric_normal = vAB.Cross(vBC);
498 curFace->geometric_normal = curFace->geometric_normal/curFace->geometric_normal.Norm();
499
500 //=========================================== Calculate Assigned normal
501 chi_mesh::Vertex nA = this->normals_.at(curFace->n_index[0]);
502 chi_mesh::Vertex nB = this->normals_.at(curFace->n_index[1]);
503 chi_mesh::Vertex nC = this->normals_.at(curFace->n_index[2]);
504
505 chi_mesh::Vector3 nAvg = (nA + nB + nC) / 3.0;
506 nAvg = nAvg/nAvg.Norm();
507
508 curFace->assigned_normal = nAvg;
509
510 //=========================================== Compute face center
511 curFace->face_centroid = (vA+vB+vC)/3.0;
512 }
513 std::vector<chi_mesh::PolyFace*>::iterator curPFace;
514 for (curPFace = this->poly_faces_.begin();
515 curPFace!=this->poly_faces_.end();
516 curPFace++)
517 {
518 chi_mesh::Vector3 centroid;
519 int num_verts = (*curPFace)->v_indices.size();
520 for (int v=0; v<num_verts; v++)
521 centroid = centroid + vertices_[(*curPFace)->v_indices[v]];
522
523 centroid = centroid/num_verts;
524
525 (*curPFace)->face_centroid = centroid;
526
527 chi_mesh::Vector3 n = (vertices_[(*curPFace)->v_indices[1]] -
528 vertices_[(*curPFace)->v_indices[0]]).Cross(
529 centroid - vertices_[(*curPFace)->v_indices[1]]);
530 n = n/n.Norm();
531
532 (*curPFace)->geometric_normal = n;
533 }
534
535 UpdateInternalConnectivity();
536
537 //============================================= Check each vertex is accounted
538 Chi::log.Log()
539 << "Surface mesh loaded with "
540 << this->faces_.size() << " triangle faces and "
541 << this->poly_faces_.size() << " polygon faces.";
542 //chi::Exit(EXIT_FAILURE);
543
544 return 0;
545}
546
547//#########################################################
548/**Creates a 2D orthogonal mesh from a set of vertices in x and y.
549 * The vertices along a dimension merely represents the divisions. They
550 * are not the complete vertices defining a cell. For example:
551\code
552std::vector<chi_mesh::Vertex> vertices_x = {0.0,1.0,2.0};
553std::vector<chi_mesh::Vertex> vertices_y = {0.0,1.0,2.0};
554chi_mesh::SurfaceMesh::CreateFromDivisions(vertices_x,vertices_y);
555\endcode
556
557This code will create a 2x2 mesh with \f$ \vec{x} \in [0,2]^2 \f$.
558*/
560 CreateFromDivisions(std::vector<double>& vertices_1d_x,
561 std::vector<double>& vertices_1d_y)
562{
563 //======================================== Checks if vertices are empty
564 if (vertices_1d_x.empty())
565 {
567 << "chi_mesh::SurfaceMesh::CreateFromDivisions. Empty vertex_x list.";
568 Chi::Exit(EXIT_FAILURE);
569 }
570 if (vertices_1d_y.empty())
571 {
573 << "chi_mesh::SurfaceMesh::CreateFromDivisions. Empty vertex_y list.";
574 Chi::Exit(EXIT_FAILURE);
575 }
576
577 //======================================== Populate 2D vertices
578 int Nvx = vertices_1d_x.size();
579 int Nvy = vertices_1d_y.size();
580
581 int Ncx = Nvx - 1;
582 int Ncy = Nvy - 1;
583
584 std::vector<chi_mesh::Vertex> vertices_x;
585 std::vector<chi_mesh::Vertex> vertices_y;
586
587 vertices_x.reserve(Nvx);
588 vertices_y.reserve(Nvy);
589
590 for (double v : vertices_1d_x)
591 vertices_x.emplace_back(v,0.0,0.0);
592
593 for (double v : vertices_1d_y)
594 vertices_y.emplace_back(0.0,v,0.0);
595
596 //======================================== Create surface mesh
597 auto surf_mesh = new chi_mesh::SurfaceMesh();
598
599 //============================== Populate vertices
600 std::vector<std::vector<int>> vert_ij_map(Nvx,std::vector<int>(Nvx,-1));
601 for (int i=0; i<Nvy; ++i)
602 {
603 for (int j=0; j<Nvx; ++j)
604 {
605 surf_mesh->vertices_.push_back(vertices_x[j] + vertices_y[i]);
606 vert_ij_map[i][j] = surf_mesh->vertices_.size() - 1;
607 }//for j
608 }//for i
609
610 //============================== Populate polyfaces
611 for (int i=0; i<Ncy; ++i)
612 {
613 for (int j=0; j<Ncx; ++j)
614 {
615 auto new_face = new chi_mesh::PolyFace();
616 new_face->v_indices.push_back(vert_ij_map[i ][j ]);
617 new_face->v_indices.push_back(vert_ij_map[i ][j+1]);
618 new_face->v_indices.push_back(vert_ij_map[i+1][j+1]);
619 new_face->v_indices.push_back(vert_ij_map[i+1][j]);
620
621 for (int v=0;v<(new_face->v_indices.size());v++)
622 {
623 int* side_indices = new int[4];
624
625 side_indices[0] = new_face->v_indices[v];
626 side_indices[1] = new_face->v_indices[v+1];
627 side_indices[2] = -1;
628 side_indices[3] = -1;
629
630 if ((v+1)>=new_face->v_indices.size())
631 side_indices[1] = new_face->v_indices[0];
632
633 new_face->edges.push_back(side_indices);
634 }//for v
635
636 surf_mesh->poly_faces_.push_back(new_face);
637 }//for j
638 }//for i
639
640 //============================== Compute normals
641 for (auto poly_face : surf_mesh->poly_faces_)
642 {
643 chi_mesh::Vector3 centroid;
644 int num_verts = poly_face->v_indices.size();
645 for (int v=0; v<num_verts; v++)
646 centroid = centroid + surf_mesh->vertices_[poly_face->v_indices[v]];
647
648 centroid = centroid/num_verts;
649
650 poly_face->face_centroid = centroid;
651
652 chi_mesh::Vector3 n = (surf_mesh->vertices_[poly_face->v_indices[1]] -
653 surf_mesh->vertices_[poly_face->v_indices[0]]).Cross(
654 centroid - surf_mesh->vertices_[poly_face->v_indices[1]]);
655 n = n/n.Norm();
656
657 poly_face->geometric_normal = n;
658 }
659
660 surf_mesh->UpdateInternalConnectivity();
661
662 return surf_mesh;
663}
664
665//#########################################################
666/** Loads a surface mesh from gmsh's file format.*/
668ImportFromMshFiles(const char* fileName, bool as_poly=false)
669{
670 const std::string node_section_name="$Nodes";
671 const std::string elements_section_name = "$Elements";
672
673 std::istringstream iss;
674 std::string line;
675
676 std::ifstream file;
677 file.open(std::string(fileName));
678
679 if (!file.is_open())
680 {
682 << "Failed to open file: "<< fileName <<" in call "
683 << "to ImportFromMshFiles \n";
684 Chi::Exit(EXIT_FAILURE);
685 }
686
687 //=================================================== Find section with node information
688 // and then read information
689 while (std::getline(file, line))
690 {
691 if ( node_section_name.compare(line)==0 )
692 break;
693 }
694
695 std::getline(file, line);
696 iss = std::istringstream(line);
697 int num_nodes;
698 if ( !(iss >> num_nodes) )
699 {
700 Chi::log.LogAllError()<<"Failed while trying to read the number of nodes.\n";
701 Chi::Exit(EXIT_FAILURE);
702 }
703
704 vertices_.resize(num_nodes);
705
706 for (int n=0; n<num_nodes; n++)
707 {
708 std::getline(file, line);
709 iss = std::istringstream(line);
710
711 chi_mesh::Vertex vertex;
712 int vert_index;
713 if ( !(iss >> vert_index) )
714 {
715 Chi::log.LogAllError()<<"Failed to read vertex index.\n";
716 Chi::Exit(EXIT_FAILURE);
717 }
718
719 if (!(iss >> vertex.x >> vertex.y >> vertex.z))
720 {
721 Chi::log.LogAllError()<<"Failed while reading the vertex coordinates.\n";
722 Chi::Exit(EXIT_FAILURE);
723 }
724
725 vertices_[vert_index - 1] = vertex;
726 }
727
728
729 //=================================================== Find the element listing section
730 // and first read the boundary data
731 file.seekg(0);
732 while (std::getline(file, line))
733 {
734 if ( elements_section_name.compare(line)==0 )
735 break;
736 }
737
738 std::getline(file, line);
739 iss = std::istringstream(line);
740 int num_elems;
741 if (!(iss >> num_elems))
742 {
743 Chi::log.LogAllError()<<"Failed to read number of elements.\n";
744 Chi::Exit(EXIT_FAILURE);
745 }
746
747 for (int n=0; n<num_elems; n++)
748 {
749 int elem_type, num_tags, physical_reg, tag, element_index;
751 std::getline(file, line);
752 iss = std::istringstream(line);
753
754 if ( !(iss >> element_index >> elem_type >> num_tags) )
755 {
756 Chi::log.LogAllError()<<"Failed while reading element index, element type, and number of tags.\n";
757 Chi::Exit(EXIT_FAILURE);
758 }
759
760 if( !(iss>>physical_reg) )
761 {
762 Chi::log.LogAllError()<<"Failed while reading physical region.\n";
763 Chi::Exit(EXIT_FAILURE);
764 }
765
766 for (int i=1; i<num_tags; i++)
767 if( !(iss >> tag) )
768 {
769 Chi::log.LogAllError()<<"Failed when reading tags.\n";
770 Chi::Exit(EXIT_FAILURE);
771 }
772
773 if (elem_type == 2)
774 {
775 const int num_nodes = 3;
776
777 int nodes[num_nodes];
778 for (int i=0; i<num_nodes; i++)
779 if ( !(iss >> nodes[i]) )
780 {
781 Chi::log.LogAllError()<<"Failed when reading element node index.\n";
782 Chi::Exit(EXIT_FAILURE);
783 }
784
785 newFace->v_indices.resize(num_nodes);
786 for (int i=0; i<num_nodes; i++)
787 newFace->v_indices[i] = nodes[i]-1;
788
789 } else if (elem_type == 3)
790 {
791 const int num_nodes = 4;
792
793 int nodes[num_nodes];
794 for (int & node : nodes)
795 if ( !(iss >> node) )
796 {
797 Chi::log.LogAllError()<<"Failed when reading element node index.\n";
798 Chi::Exit(EXIT_FAILURE);
799 }
800
801 newFace->v_indices.resize(num_nodes);
802 for (int i=0; i<num_nodes; i++)
803 newFace->v_indices[i] = nodes[i]-1;
804
805 } else
806 {
807 continue;
808 }
809
810 const size_t total_nodes = newFace->v_indices.size();
811
812 for (size_t e=0; e<total_nodes; e++)
813 {
814 int* side_indices = new int[total_nodes];
815 side_indices[0] = newFace->v_indices[e];
816
817 if (e<total_nodes-1)
818 side_indices[1] = newFace->v_indices[e+1];
819 else
820 side_indices[1] = newFace->v_indices[0];
821
822 side_indices[2] = -1;
823 side_indices[3] = -1;
824
825 newFace->edges.push_back(side_indices);
826 }
827
828 poly_faces_.push_back(newFace);
829 physical_region_map_.push_back(physical_reg);
830 }
831
832 file.close();
833
834 //======================================================= Calculate face properties
835 for (const auto& poly_face : poly_faces_)
836 {
837 chi_mesh::Vector3 centroid;
838 size_t num_verts = poly_face->v_indices.size();
839
840 for (size_t v=0; v<num_verts; v++)
841 centroid = centroid + vertices_[poly_face->v_indices[v]];
842
843 centroid = centroid/static_cast<double>(num_verts);
844
845 poly_face->face_centroid = centroid;
846
847 chi_mesh::Vector3 n = (vertices_[poly_face->v_indices[1]] -
848 vertices_[poly_face->v_indices[0]]).Cross(
849 centroid - vertices_[poly_face->v_indices[1]]);
850
851 n = n/n.Norm();
852
853 poly_face->geometric_normal = n;
854 }
855
856 UpdateInternalConnectivity();
857
858 return 0;
859}
860
861//#########################################################
862/**Exports the triangular faces of a surface mesh to
863 * wavefront .obj files.*/
865{
866
867// if (this->faces.empty())
868// {
869// std::cout << "Cannot export empty SurfaceMesh\n";
870// return;
871// }
872 FILE* outputFile = fopen(fileName,"w");
873 if (outputFile==nullptr)
874 {
875 printf("Error creating file %s!\n",fileName);
876 return;
877 }
878
879 fprintf(outputFile,"# Exported mesh file from tringulation script\n");
880 fprintf(outputFile,"o %s\n","ChitechTriMesh");
881
882 std::vector<chi_mesh::Vertex>::iterator cur_v;
883 for (cur_v = this->vertices_.begin();
884 cur_v != this->vertices_.end();
885 cur_v++)
886 {
887 fprintf(outputFile,"v %9.6f %9.6f %9.6f\n",cur_v->x,cur_v->y,cur_v->z);
888 }
889
890 for (unsigned ell=0; ell<this->lines_.size(); ell++)
891 {
892 fprintf(outputFile, "l %d %d \n", lines_[ell].v_index[0] + 1,
893 lines_[ell].v_index[1] + 1);
894 }
895
896 if (!faces_.empty())
897 {
898 chi_mesh::Face first_face = this->faces_.front();
899 fprintf(outputFile,"vn %.4f %.4f %.4f\n", first_face.geometric_normal.x,
900 first_face.geometric_normal.y,
901 first_face.geometric_normal.z);
902 fprintf(outputFile,"s off\n");
903
904 std::vector<chi_mesh::Face>::iterator cur_face;
905 for (cur_face = this->faces_.begin();
906 cur_face != this->faces_.end();
907 cur_face++)
908 {
909 fprintf(outputFile,"f %d//1 %d//1 %d//1\n",cur_face->v_index[0]+1,
910 cur_face->v_index[1]+1,
911 cur_face->v_index[2]+1);
912 }
913 }
914 if (!poly_faces_.empty())
915 {
916 chi_mesh::PolyFace* first_face = this->poly_faces_.front();
917 fprintf(outputFile,"vn %.4f %.4f %.4f\n", first_face->geometric_normal.x,
918 first_face->geometric_normal.y,
919 first_face->geometric_normal.z);
920 fprintf(outputFile,"s off\n");
921
922 for (auto & poly_face : poly_faces_)
923 {
924 fprintf(outputFile,"f ");
925 for (int v_indice : poly_face->v_indices)
926 {
927 fprintf(outputFile,"%d//1 ",v_indice+1);
928 }
929 fprintf(outputFile,"\n");
930 }
931 }
932
933 fclose(outputFile);
934 printf("Exported mesh to %s\n",fileName);
935}
936
937//#########################################################
938/**Exports a PSLG to triangle1.6's .poly format.*/
940{
941 FILE* outputFile = fopen(fileName,"w");
942 if (outputFile==nullptr)
943 {
944 printf("Error creating file %s!\n",fileName);
945 return;
946 }
947
948 fprintf(outputFile, "%lu 2 0 0\n", vertices_.size());
949 for (int v=0; v < vertices_.size(); v++)
950 {
951 fprintf(outputFile, "%d %.15f %.15f 0\n",v+1, vertices_[v].x, vertices_[v].y);
952 }
953
954 fprintf(outputFile, "%lu 0\n", lines_.size());
955 for (int e=0; e < lines_.size(); e++)
956 {
957 fprintf(outputFile, "%d %d %d\n",e+1, lines_[e].v_index[0] + 1,
958 lines_[e].v_index[1] + 1);
959 }
960
961 fprintf(outputFile,"0");
962
963
964 fclose(outputFile);
965 printf("Exported mesh to %s\n",fileName);
966}
static void Exit(int error_code)
Definition: chi_runtime.cc:342
static chi::ChiLog & log
Definition: chi_runtime.h:81
LogStream LogAllError()
Definition: chi_log.h:239
LogStream Log(LOG_LVL level=LOG_0)
Definition: chi_log.cc:35
static SurfaceMesh * CreateFromDivisions(std::vector< double > &vertices_1d_x, std::vector< double > &vertices_1d_y)
int ImportFromTriangleFiles(const char *fileName, bool as_poly)
void ExportToOBJFile(const char *fileName)
void ExportToPolyFile(const char *fileName)
std::vector< chi_mesh::Edge > lines_
int ImportFromMshFiles(const char *fileName, bool as_poly)
std::vector< chi_mesh::PolyFace * > poly_faces_
Polygonal faces.
std::vector< chi_mesh::Vertex > tex_vertices_
Texture vertices.
std::vector< chi_mesh::Vertex > vertices_
int ImportFromOBJFile(const std::string &fileName, bool as_poly=false, const chi_mesh::Vector3 &transform=Vector3(0, 0, 0))
std::vector< chi_mesh::Face > faces_
std::vector< chi_mesh::Normal > normals_
chi_mesh::Vertex vertices[2]
Vector vertices.
int v_index[2]
Indices of the vertices.
chi_mesh::Normal geometric_normal
Definition: chi_meshface.h:13
int n_index[3]
Definition: chi_meshface.h:9
int v_index[3]
Definition: chi_meshface.h:8
int e_index[3][4]
Definition: chi_meshface.h:11
std::vector< int > v_indices
Definition: chi_meshface.h:91
std::vector< int * > edges
Definition: chi_meshface.h:92
chi_mesh::Normal geometric_normal
Definition: chi_meshface.h:95
std::string PrintStr() const
double x
Element-0.
Vector3 Cross(const Vector3 &that) const
double y
Element-1.
double z
Element-2.
double Norm() const