15 const std::string fname =
"chi_mesh::UnpartitionedMesh::ReadFromWavefrontOBJ";
24 <<
"to ImportFromOBJFile \n";
29 Chi::log.
Log() <<
"Making Unpartitioned mesh from wavefront file "
32 typedef std::pair<uint64_t, uint64_t>
Edge;
36 std::vector<LightWeightCell*> cells;
37 std::vector<Edge> edges;
40 std::vector<BlockData> block_data;
41 std::vector<chi_mesh::Vertex> file_vertices;
44 std::string file_line;
45 std::string delimiter =
" ";
47 while (std::getline(file, file_line))
50 size_t beg_of_word = file_line.find_first_not_of(delimiter);
51 size_t end_of_word = file_line.find(delimiter, beg_of_word - beg_of_word);
52 std::string first_word = file_line.substr(beg_of_word, end_of_word);
55 if (first_word ==
"o")
57 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
58 end_of_word = file_line.find(delimiter, beg_of_word);
59 sub_word = file_line.substr(beg_of_word, end_of_word - beg_of_word);
61 std::string block_name = sub_word;
62 block_data.push_back({block_name, {}});
65 if (first_word ==
"usemtl")
68 <<
"New material at cell count: " << block_data.back().cells.size();
73 if (first_word ==
"v")
76 for (
int k = 1; k <= 3; k++)
79 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
80 end_of_word = file_line.find(delimiter, beg_of_word);
81 sub_word = file_line.substr(beg_of_word, end_of_word - beg_of_word);
86 double numValue = std::stod(sub_word);
88 if (k == 1) newVertex.
x = numValue;
90 newVertex.
y = numValue;
92 newVertex.
z = numValue;
96 catch (
const std::invalid_argument& ia)
99 <<
"Failed to convert vertex in line " << file_line << std::endl;
103 if (end_of_word == std::string::npos) {
break; }
105 file_vertices.push_back(newVertex);
109 if (first_word ==
"f")
111 size_t number_of_verts =
112 std::count(file_line.begin(), file_line.end(),
'/') / 2;
116 else if (number_of_verts == 4)
120 cell->material_id = material_id;
123 for (
size_t k = 1; k <= number_of_verts; k++)
126 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
127 end_of_word = file_line.find(delimiter, beg_of_word);
128 sub_word = file_line.substr(beg_of_word, end_of_word - beg_of_word);
131 size_t first_dash = sub_word.find(
'/');
132 size_t last_dash = sub_word.find_last_of(
'/');
135 std::string vert_word = sub_word.substr(0, first_dash - 0);
136 std::string norm_word =
137 sub_word.substr(last_dash + 1, sub_word.length() - last_dash - 1);
142 int numValue = std::stoi(vert_word);
143 cell->vertex_ids.push_back(numValue - 1);
145 catch (
const std::invalid_argument& ia)
148 << file_line << std::endl;
152 if (end_of_word == std::string::npos) {
break; }
156 const size_t num_verts = cell->vertex_ids.size();
157 for (uint64_t v = 0; v < num_verts; ++v)
164 (v < (num_verts - 1)) ? cell->vertex_ids[v + 1] : cell->vertex_ids[0];
166 cell->faces.push_back(std::move(face));
169 if (block_data.empty())
170 throw std::logic_error(
171 fname +
": Could not add cell to block-data. "
172 "This normally indicates that the file does not have the "
173 "\"o Object Name\" entry.");
175 block_data.back().cells.push_back(cell);
179 if (first_word ==
"l")
182 for (
int k = 1; k <= 2; ++k)
185 beg_of_word = file_line.find_first_not_of(delimiter, end_of_word);
186 end_of_word = file_line.find(delimiter, beg_of_word);
187 sub_word = file_line.substr(beg_of_word, end_of_word - beg_of_word);
192 int vertex_id = std::stoi(sub_word);
193 if (k == 1) edge.first = vertex_id - 1;
194 if (k == 2) edge.second = vertex_id - 1;
198 catch (
const std::invalid_argument& ia)
201 <<
"Failed to text to integer in line " << file_line << std::endl;
205 if (block_data.empty())
206 throw std::logic_error(
207 fname +
": Could not add edge to block-data. "
208 "This normally indicates that the file does not have the "
209 "\"o Object Name\" entry.");
211 block_data.back().edges.push_back(edge);
218 for (
const auto& block : block_data)
219 for (
const auto& cell : block.cells)
220 for (
const auto vid : cell->vertex_ids)
223 "Cell vertex id " + std::to_string(vid) +
224 " not in list of vertices read (size=" +
225 std::to_string(file_vertices.size()) +
").");
229 std::vector<size_t> bndry_block_ids;
230 size_t num_cell_blocks = 0;
231 size_t main_block_id = 0;
232 for (
size_t block_id = 0; block_id < block_data.size(); ++block_id)
234 if (not block_data[block_id].edges.empty())
235 bndry_block_ids.push_back(block_id);
236 if (not block_data[block_id].cells.empty())
239 main_block_id = block_id;
243 if (num_cell_blocks != 1)
244 throw std::logic_error(
246 ": More than one cell-block has been read "
247 "from the file. Only a single face-containing object is supported. "
248 "If you exported this mesh from blender, be sure to export "
249 "\"selection only\"");
252 std::vector<chi_mesh::Vertex> cell_vertices;
255 std::vector<size_t> vertex_map;
256 vertex_map.reserve(file_vertices.size());
257 for (
size_t m = 0; m < file_vertices.size(); ++m)
258 vertex_map.push_back(m);
261 std::set<size_t> cell_vertex_id_set;
262 for (
const auto& cell_ptr : block_data.at(main_block_id).cells)
263 for (
size_t vid : cell_ptr->vertex_ids)
264 cell_vertex_id_set.insert(vid);
269 for (
size_t vid : cell_vertex_id_set)
271 cell_vertices.push_back(file_vertices[vid]);
272 vertex_map[vid] = new_id;
278 std::set<size_t> bndry_vertex_id_set;
279 for (
size_t block_id : bndry_block_ids)
280 for (
const auto& edge : block_data[block_id].edges)
282 bndry_vertex_id_set.insert(edge.first);
283 bndry_vertex_id_set.insert(edge.second);
288 for (
size_t bvid : bndry_vertex_id_set)
290 const auto& bndry_vertex = file_vertices[bvid];
292 bool match_found =
false;
293 for (
size_t cvid = 0; cvid < cell_vertices.size(); ++cvid)
295 const auto& cell_vertex = cell_vertices[cvid];
297 if ((bndry_vertex - cell_vertex).NormSquare() < 1.0e-12)
299 vertex_map[bvid] = cvid;
305 throw std::logic_error(
307 ": Failed to map a boundary vertex to"
308 "any cell vertex. Check that the edges are conformal with the "
309 "object containing the faces.");
314 for (
auto& cell_ptr : block_data.at(main_block_id).cells)
316 for (uint64_t& vid : cell_ptr->vertex_ids)
317 vid = vertex_map[vid];
319 for (
auto& face : cell_ptr->faces)
320 for (uint64_t& vid : face.vertex_ids)
321 vid = vertex_map[vid];
326 for (
size_t block_id : bndry_block_ids)
327 for (
auto& edge : block_data[block_id].edges)
329 edge.first =
static_cast<int>(vertex_map[edge.first]);
330 edge.second =
static_cast<int>(vertex_map[edge.second]);
334 this->
raw_cells_ = block_data[main_block_id].cells;
343 if (bndry_block_ids.empty())
349 std::vector<LightWeightFace*> bndry_faces;
351 for (
auto& face : cell_ptr->faces)
352 if (not face.has_neighbor) bndry_faces.push_back(&face);
355 for (
size_t bid : bndry_block_ids)
357 const auto& bndry_edges = block_data[bid].edges;
359 size_t num_faces_boundarified = 0;
360 for (
const auto& edge : bndry_edges)
362 std::set<size_t> edge_vert_id_set({edge.first, edge.second});
364 for (
auto& face_ptr : bndry_faces)
366 const auto& vert_ids = face_ptr->vertex_ids;
367 std::set<size_t> face_vert_id_set(vert_ids.begin(), vert_ids.end());
369 if (face_vert_id_set == edge_vert_id_set)
371 face_ptr->neighbor = bndry_id;
372 ++num_faces_boundarified;
378 Chi::log.
Log() <<
"UnpartitionedMesh: assigned " << num_faces_boundarified
379 <<
" faces to boundary id " << bndry_id <<
" with name "
380 << block_data[bid].name;
#define ChiLogicalErrorIf(condition, message)
static void Exit(int error_code)
static chi::MPI_Info & mpi
LogStream Log(LOG_LVL level=LOG_0)
void ComputeCentroidsAndCheckQuality()
void BuildMeshConnectivity()
std::vector< chi_mesh::Vertex > vertices_
void ReadFromWavefrontOBJ(const Options &options)
MeshAttributes attributes_
std::vector< LightWeightCell * > raw_cells_
std::pair< uint64_t, uint64_t > Edge
std::vector< uint64_t > vertex_ids
std::map< uint64_t, std::string > boundary_id_map