OGS
FileIO::Gocad::GocadAsciiReader Namespace Reference

Enumerations

enum class  NodeType { UNSPECIFIED , VRTX , PVRTX }

Functions

void checkMeshNames (std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
bool isCommentLine (std::string const &str)
 Checks if the current line is a comment.
bool skipToEND (std::ifstream &in)
 Parses current section until END-tag is reached.
bool isKeyword (DataType const t, std::string const &line)
 Checks if current line is a designated keyword for a GoCAD data set.
DataType datasetFound (std::ifstream &in)
 Checks if a GoCAD data set begins at the current stream position.
void checkLineEndings (std::string const &file_name)
 Checks if current line is a designated keyword for a GoCAD data set.
bool parseHeader (std::ifstream &in, std::string &mesh_name)
 Parses the HEADER section (everything except the name is ignored right now)
bool parsePropertyClass (std::ifstream &in)
std::string propertyCheck (std::string const &string)
 Checks if the current line starts with one of the allowed keywords.
bool parseProperties (std::ifstream &in, std::vector< std::string > const &names, MeshLib::Properties &mesh_prop)
MeshLib::NodecreateNode (std::stringstream &sstr)
bool parseAtomRegionIndicators (std::ifstream &in)
bool parseNodes (std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::map< std::size_t, std::size_t > &node_id_map, MeshLib::Properties const &mesh_prop)
 Parses the node data for the current mesh.
bool parseLineSegments (std::ifstream &in, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > const &node_id_map, MeshLib::Properties &mesh_prop)
 Parses the segments of the current line.
bool parseLine (std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > &node_id_map, MeshLib::Properties &mesh_prop)
 Parses line information (nodes, segments, properties)
bool parseElements (std::ifstream &in, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > const &node_id_map, MeshLib::Properties &mesh_prop)
 Parses the element data for the current mesh.
bool parseSurface (std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > &node_id_map, MeshLib::Properties &mesh_prop)
 Parses the surface information (nodes, triangles, properties)
template<typename T>
MeshLib::MeshcreateMesh (std::ifstream &in, DataType type, std::string &mesh_name, MeshLib::Properties &mesh_prop, T parser, bool const flip_elevation)
 Converts parsed data into mesh.
MeshLib::MeshreadData (std::ifstream &in, DataType const &type, std::string &mesh_name)
 Reads one mesh contained in the file (there may be more than one!)
bool readFile (std::string const &file_name, std::vector< std::unique_ptr< MeshLib::Mesh > > &meshes, DataType const export_type=DataType::ALL)
 Reads the specified file and writes data into internal mesh vector.

Variables

const std::string mat_id_name = "MaterialIDs"
const std::string eof_error = "Error: Unexpected end of file."

Enumeration Type Documentation

◆ NodeType

Function Documentation

◆ checkLineEndings()

void FileIO::Gocad::GocadAsciiReader::checkLineEndings ( std::string const & file_name)

Checks if current line is a designated keyword for a GoCAD data set.

Definition at line 116 of file GocadAsciiReader.cpp.

117{
118#ifndef _WIN32
119 std::ifstream in(file_name);
120 if (in.is_open())
121 {
122 std::string line;
123 std::getline(in, line);
124 if (line.back() == '\r')
125 {
126 OGS_FATAL(
127 "Error in input file: {:s}. The line endings are in windows "
128 "format. To read this file under UNIX, transform the input "
129 "file to unix style line endings (e.g. dos2unix).",
130 file_name);
131 }
132 }
133#endif
134}
#define OGS_FATAL(...)
Definition Error.h:19

References OGS_FATAL.

Referenced by readFile().

◆ checkMeshNames()

void FileIO::Gocad::GocadAsciiReader::checkMeshNames ( std::vector< std::unique_ptr< MeshLib::Mesh > > const & meshes)

A GoCAD file may contain multiple datasets with the same name. To avoid conflicts when writing meshes, a unique id is appended to the mesh name if another dataset with the same name exists.

Definition at line 37 of file GocadAsciiReader.cpp.

38{
39 std::size_t const n_meshes = meshes.size();
40 for (std::size_t i = 0; i < n_meshes; ++i)
41 {
42 std::string const& name = meshes[i]->getName();
43 for (std::size_t j = i + 1; j < n_meshes; ++j)
44 {
45 if (meshes[j]->getName() == name)
46 {
47 std::string const id_str = std::to_string(meshes[j]->getID());
48 meshes[i]->setName(name + "--importID-" + id_str);
49 break;
50 }
51 }
52 }
53}
std::string getName(std::string const &line)
Returns the name/title from the "Zone"-description.

References getName().

Referenced by readFile().

◆ createMesh()

template<typename T>
MeshLib::Mesh * FileIO::Gocad::GocadAsciiReader::createMesh ( std::ifstream & in,
DataType type,
std::string & mesh_name,
MeshLib::Properties & mesh_prop,
T parser,
bool const flip_elevation )

Converts parsed data into mesh.

Definition at line 547 of file GocadAsciiReader.cpp.

551{
552 std::vector<MeshLib::Node*> nodes;
553 std::vector<MeshLib::Element*> elems;
554 std::map<std::size_t, std::size_t> node_id_map;
555 INFO("Parsing {:s} {:s}.", dataType2ShortString(type), mesh_name);
556 bool return_val;
557 return_val = parser(in, nodes, elems, node_id_map, mesh_prop);
558
559 if (return_val)
560 {
561 if (flip_elevation)
562 {
563 std::for_each(nodes.begin(), nodes.end(),
564 [](MeshLib::Node* n) { (*n)[2] *= -1; });
565 }
566 return new MeshLib::Mesh(mesh_name, nodes, elems,
567 true /* compute_element_neighbors */,
568 mesh_prop);
569 }
570 ERR("Error parsing {:s} {:s}.", dataType2ShortString(type), mesh_name);
571 BaseLib::cleanupVectorElements(nodes, elems);
572 return nullptr;
573}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void cleanupVectorElements(std::vector< T * > &items)
Definition Algorithm.h:249
std::string dataType2ShortString(DataType const t)
Given a Gocad DataType this returns the appropriate short form.

References BaseLib::cleanupVectorElements(), FileIO::Gocad::dataType2ShortString(), ERR(), and INFO().

Referenced by readData().

◆ createNode()

MeshLib::Node * FileIO::Gocad::GocadAsciiReader::createNode ( std::stringstream & sstr)

Definition at line 246 of file GocadAsciiReader.cpp.

247{
248 std::string keyword;
249 std::size_t id;
250 std::array<double, 3> data{};
251 sstr >> keyword >> id >> data[0] >> data[1] >> data[2];
252 return new MeshLib::Node(data, id);
253}

References MeshLib::Node.

Referenced by parseNodes().

◆ datasetFound()

DataType FileIO::Gocad::GocadAsciiReader::datasetFound ( std::ifstream & in)

Checks if a GoCAD data set begins at the current stream position.

Definition at line 84 of file GocadAsciiReader.cpp.

85{
86 std::string line;
87 while (std::getline(in, line))
88 {
89 if (line.empty() || isCommentLine(line))
90 {
91 continue;
92 }
93
94 if (isKeyword(DataType::VSET, line))
95 {
96 return DataType::VSET;
97 }
98 if (isKeyword(DataType::PLINE, line))
99 {
100 return DataType::PLINE;
101 }
102 if (isKeyword(DataType::TSURF, line))
103 {
104 return DataType::TSURF;
105 }
106 if (isKeyword(DataType::MODEL3D, line))
107 {
108 return DataType::MODEL3D;
109 }
110 ERR("No known identifier found...");
111 return DataType::UNDEFINED;
112 }
113 return DataType::UNDEFINED;
114}
bool isCommentLine(std::string const &str)
Checks if the current line is a comment.
bool isKeyword(DataType const t, std::string const &line)
Checks if current line is a designated keyword for a GoCAD data set.

References ERR(), isCommentLine(), isKeyword(), FileIO::Gocad::MODEL3D, FileIO::Gocad::PLINE, FileIO::Gocad::TSURF, FileIO::Gocad::UNDEFINED, and FileIO::Gocad::VSET.

Referenced by readFile().

◆ isCommentLine()

bool FileIO::Gocad::GocadAsciiReader::isCommentLine ( std::string const & str)

Checks if the current line is a comment.

Definition at line 56 of file GocadAsciiReader.cpp.

57{
58 return (str.substr(0, 1) == "#");
59}

Referenced by datasetFound(), parseElements(), parseLineSegments(), parseNodes(), and readData().

◆ isKeyword()

bool FileIO::Gocad::GocadAsciiReader::isKeyword ( DataType const t,
std::string const & line )

Checks if current line is a designated keyword for a GoCAD data set.

Definition at line 77 of file GocadAsciiReader.cpp.

78{
79 std::size_t str_length = dataType2String(t).length();
80 return (line.substr(0, str_length) == dataType2String(t));
81}
std::string dataType2String(DataType const t)
Given a Gocad DataType this returns the appropriate string.

References FileIO::Gocad::dataType2String().

Referenced by datasetFound().

◆ parseAtomRegionIndicators()

bool FileIO::Gocad::GocadAsciiReader::parseAtomRegionIndicators ( std::ifstream & in)

parse Atom Region Indicator section for current TFACE (currently the information in this section is ignored)

Definition at line 257 of file GocadAsciiReader.cpp.

258{
259 std::string line;
260 while (std::getline(in, line))
261 {
262 if (line.substr(0, 26) == "END_ATOM_REGION_INDICATORS")
263 {
264 return true;
265 }
266 }
267 return false;
268}

Referenced by parseNodes().

◆ parseElements()

bool FileIO::Gocad::GocadAsciiReader::parseElements ( std::ifstream & in,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & elems,
std::map< std::size_t, std::size_t > const & node_id_map,
MeshLib::Properties & mesh_prop )

Parses the element data for the current mesh.

Definition at line 442 of file GocadAsciiReader.cpp.

447{
449 *mesh_prop.getPropertyVector<int>(mat_id_name);
450 int current_mat_id(0);
451 if (!mat_ids.empty())
452 {
453 current_mat_id = (*std::max_element(mat_ids.begin(), mat_ids.end()))++;
454 }
455 std::streampos pos = in.tellg();
456 std::size_t id(0);
457 std::string line;
458 while (std::getline(in, line))
459 {
460 if (line.empty() || isCommentLine(line))
461 {
462 continue;
463 }
464 if (line.substr(0, 4) == "TRGL")
465 {
466 std::stringstream sstr(line);
467 std::string keyword;
468 std::array<std::size_t, 3> data{};
469 sstr >> keyword >> data[0] >> data[1] >> data[2];
470 std::array<MeshLib::Node*, 3> elem_nodes{};
471 for (std::size_t i = 0; i < 3; ++i)
472 {
473 auto const it = node_id_map.find(data[i]);
474 if (it == node_id_map.end() || it->second >= nodes.size())
475 {
476 ERR("Error: Node ID ({:d}) out of range (0, {:d}).",
477 data[i], nodes.back()->getID());
478 return false;
479 }
480 elem_nodes[i] = nodes[it->second];
481 }
482 elems.push_back(new MeshLib::Tri(elem_nodes, id++));
483 mat_ids.push_back(current_mat_id);
484 }
485 else
486 {
487 in.seekg(pos);
488 return true;
489 }
490 pos = in.tellg();
491 }
492 ERR("{:s}", eof_error);
493 return false;
494}
PropertyVector< T > const * getPropertyVector(std::string_view name) const
constexpr bool empty() const
constexpr PROP_VAL_TYPE * begin()
constexpr void push_back(const PROP_VAL_TYPE &value)
constexpr PROP_VAL_TYPE * end()
TemplateElement< MeshLib::TriRule3 > Tri
Definition Tri.h:15

References MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), MeshLib::PropertyVector< PROP_VAL_TYPE >::empty(), MeshLib::PropertyVector< PROP_VAL_TYPE >::end(), eof_error, ERR(), MeshLib::Properties::getPropertyVector(), isCommentLine(), mat_id_name, and MeshLib::PropertyVector< PROP_VAL_TYPE >::push_back().

Referenced by parseSurface().

◆ parseHeader()

bool FileIO::Gocad::GocadAsciiReader::parseHeader ( std::ifstream & in,
std::string & mesh_name )

Parses the HEADER section (everything except the name is ignored right now)

Definition at line 137 of file GocadAsciiReader.cpp.

138{
139 std::string line;
140 while (std::getline(in, line))
141 {
142 if (line.substr(0, 5) == "name:")
143 {
144 mesh_name = line.substr(5, line.length() - 5);
145 BaseLib::trim(mesh_name, ' ');
146 // replace chars that will prevent writing the file
147 std::replace(mesh_name.begin(), mesh_name.end(), '/', '-');
148 std::replace(mesh_name.begin(), mesh_name.end(), '\\', '-');
149 }
150 else if (line.substr(0, 1) == "}")
151 {
152 return true;
153 }
154 // ignore all other header parameters
155 }
156 ERR("{:s}", eof_error);
157 return false;
158}
void trim(std::string &str, char ch)

References eof_error, ERR(), and BaseLib::trim().

Referenced by readData().

◆ parseLine()

bool FileIO::Gocad::GocadAsciiReader::parseLine ( std::ifstream & in,
std::vector< MeshLib::Node * > & nodes,
std::vector< MeshLib::Element * > & elems,
std::map< std::size_t, std::size_t > & node_id_map,
MeshLib::Properties & mesh_prop )

Parses line information (nodes, segments, properties)

Definition at line 406 of file GocadAsciiReader.cpp.

411{
412 if (!parseNodes(in, nodes, node_id_map, mesh_prop))
413 {
414 return false;
415 }
416 if (!parseLineSegments(in, nodes, elems, node_id_map, mesh_prop))
417 {
418 return false;
419 }
420
421 std::string line;
422 while (std::getline(in, line))
423 {
424 std::vector<std::string> str = BaseLib::splitString(line);
425 if (str[0] == "ILINE")
426 {
427 parseLine(in, nodes, elems, node_id_map, mesh_prop);
428 return true;
429 }
430 if (line == "END")
431 {
432 return true;
433 }
434 WARN("GocadAsciiReader::parseLine() - Unknown keyword found: {:s}",
435 line);
436 }
437 ERR("{:s}", eof_error);
438 return false;
439}
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::vector< std::string > splitString(std::string const &str)
bool parseLineSegments(std::ifstream &in, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > const &node_id_map, MeshLib::Properties &mesh_prop)
Parses the segments of the current line.
bool parseLine(std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > &node_id_map, MeshLib::Properties &mesh_prop)
Parses line information (nodes, segments, properties)
bool parseNodes(std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::map< std::size_t, std::size_t > &node_id_map, MeshLib::Properties const &mesh_prop)
Parses the node data for the current mesh.

References eof_error, ERR(), parseLine(), parseLineSegments(), parseNodes(), BaseLib::splitString(), and WARN().

Referenced by parseLine(), and readData().

◆ parseLineSegments()

bool FileIO::Gocad::GocadAsciiReader::parseLineSegments ( std::ifstream & in,
std::vector< MeshLib::Node * > const & nodes,
std::vector< MeshLib::Element * > & elems,
std::map< std::size_t, std::size_t > const & node_id_map,
MeshLib::Properties & mesh_prop )

Parses the segments of the current line.

Definition at line 351 of file GocadAsciiReader.cpp.

356{
358 *mesh_prop.getPropertyVector<int>(mat_id_name);
359 int current_mat_id(0);
360 if (!mat_ids.empty())
361 {
362 current_mat_id = (*std::max_element(mat_ids.begin(), mat_ids.end()))++;
363 }
364 std::streampos pos = in.tellg();
365 std::size_t id(0);
366 std::string line;
367 while (std::getline(in, line))
368 {
369 if (line.empty() || isCommentLine(line))
370 {
371 continue;
372 }
373 if (line.substr(0, 3) == "SEG")
374 {
375 std::stringstream sstr(line);
376 std::string keyword;
377 std::array<std::size_t, 2> data{};
378 sstr >> keyword >> data[0] >> data[1];
379 std::array<MeshLib::Node*, 2> elem_nodes{};
380 for (std::size_t i = 0; i < 2; ++i)
381 {
382 auto const it = node_id_map.find(data[i]);
383 if (it == node_id_map.end() || it->second >= nodes.size())
384 {
385 ERR("Error: Node ID ({:d}) out of range (0, {:d}).",
386 data[i], nodes.back()->getID());
387 return false;
388 }
389 elem_nodes[i] = nodes[it->second];
390 }
391 elems.push_back(new MeshLib::Line(elem_nodes, id++));
392 mat_ids.push_back(current_mat_id);
393 }
394 else
395 {
396 in.seekg(pos);
397 return true;
398 }
399 pos = in.tellg();
400 }
401 ERR("{:s}", eof_error);
402 return false;
403}
TemplateElement< MeshLib::LineRule2 > Line
Definition Line.h:14

References MeshLib::PropertyVector< PROP_VAL_TYPE >::begin(), MeshLib::PropertyVector< PROP_VAL_TYPE >::empty(), MeshLib::PropertyVector< PROP_VAL_TYPE >::end(), eof_error, ERR(), MeshLib::Properties::getPropertyVector(), isCommentLine(), mat_id_name, and MeshLib::PropertyVector< PROP_VAL_TYPE >::push_back().

Referenced by parseLine().

◆ parseNodes()

bool FileIO::Gocad::GocadAsciiReader::parseNodes ( std::ifstream & in,
std::vector< MeshLib::Node * > & nodes,
std::map< std::size_t, std::size_t > & node_id_map,
MeshLib::Properties const & mesh_prop )

Parses the node data for the current mesh.

Definition at line 271 of file GocadAsciiReader.cpp.

275{
277 std::streampos pos = in.tellg();
278 std::string line;
279 while (std::getline(in, line))
280 {
281 std::vector<std::string> str = BaseLib::splitString(line);
282 if (line.substr(0, 3) == "SEG" || line.substr(0, 4) == "TRGL")
283 {
284 in.seekg(pos);
285 return true;
286 }
287
288 if (line.substr(0, 28) == "BEGIN_ATOM_REGION_INDICATORS")
289 {
291 {
292 ERR("File ended while parsing Atom Region Indicators...");
293 return false;
294 }
295 return true;
296 }
297
298 if (line.empty() || isCommentLine(line))
299 {
300 continue;
301 }
302 if (!(line.substr(0, 4) == "VRTX" || line.substr(0, 5) == "PVRTX" ||
303 line.substr(0, 4) == "ATOM"))
304 {
305 WARN("GocadAsciiReader::parseNodes() - Unknown keyword found: {:s}",
306 line);
307 continue;
308 }
309
310 std::stringstream sstr(line);
311 if (line.substr(0, 4) == "VRTX" && t != NodeType::PVRTX)
312 {
313 t = NodeType::VRTX;
314 nodes.push_back(createNode(sstr));
315 }
316 else if (line.substr(0, 5) == "PVRTX" && t != NodeType::VRTX)
317 {
318 t = NodeType::PVRTX;
319 nodes.push_back(createNode(sstr));
320 for (auto [name, property] : mesh_prop)
321 {
322 if (name == mat_id_name)
323 {
324 continue;
325 }
326 if (auto p = dynamic_cast<MeshLib::PropertyVector<double>*>(
327 property))
328 {
329 double value;
330 sstr >> value;
331 p->push_back(value);
332 }
333 }
334 }
335 else if (line.substr(0, 4) == "ATOM")
336 {
337 std::size_t new_id;
338 std::size_t ref_id;
339 std::string keyword;
340 sstr >> keyword >> new_id >> ref_id;
341 nodes.push_back(new MeshLib::Node(nodes[ref_id]->data(), new_id));
342 }
343 node_id_map[nodes.back()->getID()] = nodes.size() - 1;
344 pos = in.tellg();
345 }
346 ERR("{:s}", eof_error);
347 return false;
348}
bool parseAtomRegionIndicators(std::ifstream &in)
MeshLib::Node * createNode(std::stringstream &sstr)

References createNode(), eof_error, ERR(), isCommentLine(), mat_id_name, parseAtomRegionIndicators(), PVRTX, BaseLib::splitString(), UNSPECIFIED, VRTX, and WARN().

Referenced by parseLine(), and parseSurface().

◆ parseProperties()

bool FileIO::Gocad::GocadAsciiReader::parseProperties ( std::ifstream & in,
std::vector< std::string > const & names,
MeshLib::Properties & mesh_prop )

Parses information of node properties. Only property names and array sizes are currently used.

Definition at line 195 of file GocadAsciiReader.cpp.

198{
199 // Because properties have no end-tag, the position of the last line is
200 // stored, so the stream can be set back if none of the allowed property-
201 // related keywords is found.
202 std::streampos pos = in.tellg();
203 std::string line;
204 while (std::getline(in, line))
205 {
206 std::string const key = propertyCheck(line);
207 // This is the intended way to exit this method:
208 // No property-related keyword has been found, so the stream is set
209 // back one line and the (unrelated) keyword can be read again in the
210 // parent method.
211 if (key.empty())
212 {
213 in.seekg(pos);
214 return true;
215 }
216
217 // Currently all property parameters except array name and size are
218 // ignored.
219 if (key == "ESIZES")
220 {
221 std::vector<std::string> prop_size = BaseLib::splitString(line);
222
223 if (names.size() != prop_size.size())
224 {
225 ERR("Error: Number of PROPERTY-names ({:d}) does not match "
226 "number of ESIZES ({:d})",
227 names.size(), prop_size.size());
228 return false;
229 }
230 std::size_t const n_names(names.size());
231 for (std::size_t i = 1; i < n_names; ++i)
232 {
233 mesh_prop.createNewPropertyVector<double>(
234 names[i],
237 }
238 }
239 // Remember current position in case the properties black ends now.
240 pos = in.tellg();
241 }
242 ERR("{:s}", eof_error);
243 return false;
244}
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
T str2number(const std::string &str)
Definition StringTools.h:53
std::string propertyCheck(std::string const &string)
Checks if the current line starts with one of the allowed keywords.

References MeshLib::Properties::createNewPropertyVector(), eof_error, ERR(), MeshLib::Node, propertyCheck(), BaseLib::splitString(), and BaseLib::str2number().

Referenced by readData().

◆ parsePropertyClass()

bool FileIO::Gocad::GocadAsciiReader::parsePropertyClass ( std::ifstream & in)

Reads PROPERTY_CLASS_HEADER sections of the file. All this information is currently ignored.

Definition at line 162 of file GocadAsciiReader.cpp.

163{
164 std::string line;
165 while (std::getline(in, line))
166 {
167 if (line.substr(0, 1) == "}")
168 {
169 return true;
170 }
171 }
172 ERR("{:s}", eof_error);
173 return false;
174}

References eof_error, and ERR().

Referenced by readData().

◆ parseSurface()

bool FileIO::Gocad::GocadAsciiReader::parseSurface ( std::ifstream & in,
std::vector< MeshLib::Node * > & nodes,
std::vector< MeshLib::Element * > & elems,
std::map< std::size_t, std::size_t > & node_id_map,
MeshLib::Properties & mesh_prop )

Parses the surface information (nodes, triangles, properties)

Definition at line 497 of file GocadAsciiReader.cpp.

502{
503 if (!parseNodes(in, nodes, node_id_map, mesh_prop))
504 {
505 return false;
506 }
507 if (!parseElements(in, nodes, elems, node_id_map, mesh_prop))
508 {
509 return false;
510 }
511
512 std::string line;
513 while (std::getline(in, line))
514 {
515 std::vector<std::string> str = BaseLib::splitString(line);
516 if (str[0] == "TFACE" || str[0] == "3DFace")
517 {
518 parseSurface(in, nodes, elems, node_id_map, mesh_prop);
519 return true;
520 }
521 if (str[0] == "BSTONE")
522 {
523 // borderstone definition - currently ignored
524 }
525 else if (str[0] == "BORDER")
526 {
527 // border tracking direction - currently ignored
528 }
529 else if (line == "END")
530 {
531 return true;
532 }
533 else
534 {
535 WARN(
536 "GocadAsciiReader::parseSurface() - Unknown keyword found: "
537 "{:s}",
538 line);
539 }
540 }
541 ERR("{:s}", eof_error);
542 return false;
543}
bool parseElements(std::ifstream &in, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > const &node_id_map, MeshLib::Properties &mesh_prop)
Parses the element data for the current mesh.
bool parseSurface(std::ifstream &in, std::vector< MeshLib::Node * > &nodes, std::vector< MeshLib::Element * > &elems, std::map< std::size_t, std::size_t > &node_id_map, MeshLib::Properties &mesh_prop)
Parses the surface information (nodes, triangles, properties)

References eof_error, ERR(), parseElements(), parseNodes(), parseSurface(), BaseLib::splitString(), and WARN().

Referenced by parseSurface(), and readData().

◆ propertyCheck()

std::string FileIO::Gocad::GocadAsciiReader::propertyCheck ( std::string const & string)

Checks if the current line starts with one of the allowed keywords.

Definition at line 177 of file GocadAsciiReader.cpp.

178{
179 std::array<std::string, 7> const property_keywords = {
180 {"PROPERTY_CLASSES", "PROP_LEGAL_RANGES", "NO_DATA_VALUES",
181 "PROPERTY_KINDS", "PROPERTY_SUBCLASSES", "UNITS", "ESIZES"}};
182
183 std::string const str = BaseLib::splitString(string)[0];
184 auto res =
185 std::find(property_keywords.begin(), property_keywords.end(), str);
186 if (res != property_keywords.end())
187 {
188 return *res;
189 }
190 return std::string("");
191}

References BaseLib::splitString().

Referenced by parseProperties().

◆ readData()

MeshLib::Mesh * FileIO::Gocad::GocadAsciiReader::readData ( std::ifstream & in,
DataType const & type,
std::string & mesh_name )

Reads one mesh contained in the file (there may be more than one!)

Definition at line 576 of file GocadAsciiReader.cpp.

579{
580 if (!parseHeader(in, mesh_name))
581 {
582 return nullptr;
583 }
584
585 MeshLib::Properties mesh_prop;
588 bool flip_elevation = false;
589 std::string line;
590 while (std::getline(in, line))
591 {
592 std::vector<std::string> str = BaseLib::splitString(line);
593 if (line.empty() || isCommentLine(line))
594 {
595 continue;
596 }
597 if (str[0] == "GOCAD_ORIGINAL_COORDINATE_SYSTEM")
598 {
599 CoordinateSystem coordinate_system;
600 if (!coordinate_system.parse(in))
601 {
602 ERR("Error parsing coordinate system.");
603 return nullptr;
604 }
605 flip_elevation = (coordinate_system.z_positive ==
607 }
608 else if (str[0] == "GEOLOGICAL_FEATURE" ||
609 str[0] == "GEOLOGICAL_TYPE" ||
610 str[0] == "STRATIGRAPHIC_POSITION" || str[0] == "REGION")
611 {
612 // geological and stratigraphic information - currently ignored
613 }
614 else if (str[0] == "PROPERTY_CLASS_HEADER")
615 {
616 if (!parsePropertyClass(in))
617 {
618 ERR("Error parsing PROPERTY_CLASS_HEADER.");
619 return nullptr;
620 }
621 }
622 else if (str[0] == "PROPERTIES")
623 {
624 if (!parseProperties(in, str, mesh_prop))
625 {
626 ERR("Error parsing PROPERTIES");
627 return nullptr;
628 }
629 }
630 else if (type == DataType::PLINE && str[0] == "ILINE")
631 {
632 return createMesh(in, type, mesh_name, mesh_prop, parseLine,
633 flip_elevation);
634 }
635 else if (type == DataType::TSURF &&
636 (str[0] == "TFACE" || str[0] == "3DFace"))
637 {
638 return createMesh(in, type, mesh_name, mesh_prop, parseSurface,
639 flip_elevation);
640 }
641 else
642 {
643 WARN("GocadAsciiReader::readData() - Unknown keyword found: {:s}",
644 line);
645 }
646 }
647 ERR("{:s}", eof_error);
648 return nullptr;
649}
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
bool parseHeader(std::ifstream &in, std::string &mesh_name)
Parses the HEADER section (everything except the name is ignored right now)
bool parsePropertyClass(std::ifstream &in)
bool parseProperties(std::ifstream &in, std::vector< std::string > const &names, MeshLib::Properties &mesh_prop)
MeshLib::Mesh * createMesh(std::ifstream &in, DataType type, std::string &mesh_name, MeshLib::Properties &mesh_prop, T parser, bool const flip_elevation)
Converts parsed data into mesh.

References MeshLib::Cell, createMesh(), MeshLib::Properties::createNewPropertyVector(), FileIO::Gocad::CoordinateSystem::Depth, eof_error, ERR(), isCommentLine(), mat_id_name, FileIO::Gocad::CoordinateSystem::parse(), parseHeader(), parseLine(), parseProperties(), parsePropertyClass(), parseSurface(), FileIO::Gocad::PLINE, BaseLib::splitString(), FileIO::Gocad::TSURF, WARN(), and FileIO::Gocad::CoordinateSystem::z_positive.

Referenced by readFile().

◆ readFile()

bool FileIO::Gocad::GocadAsciiReader::readFile ( std::string const & file_name,
std::vector< std::unique_ptr< MeshLib::Mesh > > & meshes,
DataType const export_type )

Reads the specified file and writes data into internal mesh vector.

Definition at line 651 of file GocadAsciiReader.cpp.

654{
655 std::ifstream in(file_name);
656 if (!in.is_open())
657 {
658 ERR("GocadAsciiReader::readFile(): Could not open file {:s}.",
659 file_name);
660 return false;
661 }
662
663 checkLineEndings(file_name);
664
665 DataType type;
666 while ((type = datasetFound(in)) != DataType::UNDEFINED)
667 {
668 if (export_type != DataType::ALL && type != export_type)
669 {
670 skipToEND(in);
671 continue;
672 }
673
674 if (type == DataType::VSET || type == DataType::MODEL3D)
675 {
676 if (!skipToEND(in))
677 {
678 ERR("Parsing of type {:s} is not implemented. Skipping "
679 "section.",
680 dataType2String(type));
681 return false;
682 }
683 continue;
684 }
685
686 std::string mesh_name = BaseLib::dropFileExtension(file_name) +
687 std::to_string(meshes.size() + 1);
688 std::unique_ptr<MeshLib::Mesh> mesh(readData(in, type, mesh_name));
689 if (mesh == nullptr)
690 {
691 ERR("File parsing aborted...");
692 return false;
693 }
694 meshes.push_back(std::move(mesh));
695 }
696 checkMeshNames(meshes);
697 return true;
698}
std::string dropFileExtension(std::string const &filename)
void checkLineEndings(std::string const &file_name)
Checks if current line is a designated keyword for a GoCAD data set.
bool skipToEND(std::ifstream &in)
Parses current section until END-tag is reached.
void checkMeshNames(std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
MeshLib::Mesh * readData(std::ifstream &in, DataType const &type, std::string &mesh_name)
Reads one mesh contained in the file (there may be more than one!)
DataType datasetFound(std::ifstream &in)
Checks if a GoCAD data set begins at the current stream position.

References FileIO::Gocad::ALL, checkLineEndings(), checkMeshNames(), datasetFound(), FileIO::Gocad::dataType2String(), BaseLib::dropFileExtension(), ERR(), FileIO::Gocad::MODEL3D, readData(), skipToEND(), FileIO::Gocad::UNDEFINED, and FileIO::Gocad::VSET.

Referenced by MainWindow::loadFile(), and main().

◆ skipToEND()

bool FileIO::Gocad::GocadAsciiReader::skipToEND ( std::ifstream & in)

Parses current section until END-tag is reached.

Definition at line 62 of file GocadAsciiReader.cpp.

63{
64 std::string line;
65 while (std::getline(in, line))
66 {
67 if (line == "END")
68 {
69 return true;
70 }
71 }
72 ERR("{:s}", eof_error);
73 return false;
74}

References eof_error, and ERR().

Referenced by readFile().

Variable Documentation

◆ eof_error

const std::string FileIO::Gocad::GocadAsciiReader::eof_error = "Error: Unexpected end of file."

◆ mat_id_name

const std::string FileIO::Gocad::GocadAsciiReader::mat_id_name = "MaterialIDs"

Definition at line 31 of file GocadAsciiReader.cpp.

Referenced by parseElements(), parseLineSegments(), parseNodes(), and readData().