28namespace GocadAsciiReader
38const std::string
eof_error =
"Error: Unexpected end of file.";
43void checkMeshNames(std::vector<std::unique_ptr<MeshLib::Mesh>>
const& meshes)
45 std::size_t
const n_meshes = meshes.size();
46 for (std::size_t i = 0; i < n_meshes; ++i)
48 std::string
const& name = meshes[i]->getName();
49 for (std::size_t j = i + 1; j < n_meshes; ++j)
51 if (meshes[j]->
getName() == name)
53 std::string
const id_str = std::to_string(meshes[j]->getID());
54 meshes[i]->setName(name +
"--importID-" + id_str);
64 return (str.substr(0, 1) ==
"#");
71 while (std::getline(in, line))
93 while (std::getline(in, line))
116 ERR(
"No known identifier found...");
125 std::ifstream in(file_name);
129 std::getline(in, line);
130 if (line.back() ==
'\r')
133 "Error in input file: {:s}. The line endings are in windows "
134 "format. To read this file under UNIX, transform the input "
135 "file to unix style line endings (e.g. dos2unix).",
146 while (std::getline(in, line))
148 if (line.substr(0, 5) ==
"name:")
150 mesh_name = line.substr(5, line.length() - 5);
153 std::replace(mesh_name.begin(), mesh_name.end(),
'/',
'-');
154 std::replace(mesh_name.begin(), mesh_name.end(),
'\\',
'-');
156 else if (line.substr(0, 1) ==
"}")
171 while (std::getline(in, line))
173 if (line.substr(0, 1) ==
"}")
185 std::array<std::string, 7>
const property_keywords = {
186 {
"PROPERTY_CLASSES",
"PROP_LEGAL_RANGES",
"NO_DATA_VALUES",
187 "PROPERTY_KINDS",
"PROPERTY_SUBCLASSES",
"UNITS",
"ESIZES"}};
191 std::find(property_keywords.begin(), property_keywords.end(), str);
192 if (res != property_keywords.end())
196 return std::string(
"");
202 std::vector<std::string>
const& names,
208 std::streampos pos = in.tellg();
210 while (std::getline(in, line))
229 if (names.size() != prop_size.size())
231 ERR(
"Error: Number of PROPERTY-names ({:d}) does not match "
232 "number of ESIZES ({:d})",
233 names.size(), prop_size.size());
236 std::size_t
const n_names(names.size());
237 for (std::size_t i = 1; i < n_names; ++i)
256 std::array<double, 3> data{};
257 sstr >> keyword >>
id >> data[0] >> data[1] >> data[2];
266 while (std::getline(in, line))
268 if (line.substr(0, 26) ==
"END_ATOM_REGION_INDICATORS")
278 std::vector<MeshLib::Node*>& nodes,
279 std::map<std::size_t, std::size_t>& node_id_map,
283 std::streampos pos = in.tellg();
285 while (std::getline(in, line))
288 if (line.substr(0, 3) ==
"SEG" || line.substr(0, 4) ==
"TRGL")
294 if (line.substr(0, 28) ==
"BEGIN_ATOM_REGION_INDICATORS")
298 ERR(
"File ended while parsing Atom Region Indicators...");
308 if (!(line.substr(0, 4) ==
"VRTX" || line.substr(0, 5) ==
"PVRTX" ||
309 line.substr(0, 4) ==
"ATOM"))
311 WARN(
"GocadAsciiReader::parseNodes() - Unknown keyword found: {:s}",
316 std::stringstream sstr(line);
326 for (
auto [name, property] : mesh_prop)
341 else if (line.substr(0, 4) ==
"ATOM")
346 sstr >> keyword >> new_id >> ref_id;
347 nodes.push_back(
new MeshLib::Node(nodes[ref_id]->data(), new_id));
349 node_id_map[nodes.back()->getID()] = nodes.size() - 1;
358 std::vector<MeshLib::Node*>
const& nodes,
359 std::vector<MeshLib::Element*>& elems,
360 std::map<std::size_t, std::size_t>
const& node_id_map,
365 int current_mat_id(0);
366 if (!mat_ids.empty())
368 current_mat_id = (*std::max_element(mat_ids.begin(), mat_ids.end()))++;
370 std::streampos pos = in.tellg();
373 while (std::getline(in, line))
379 if (line.substr(0, 3) ==
"SEG")
381 std::stringstream sstr(line);
383 std::array<std::size_t, 2> data{};
384 sstr >> keyword >> data[0] >> data[1];
385 std::array<MeshLib::Node*, 2> elem_nodes{};
386 for (std::size_t i = 0; i < 2; ++i)
388 auto const it = node_id_map.find(data[i]);
389 if (it == node_id_map.end() || it->second >= nodes.size())
391 ERR(
"Error: Node ID ({:d}) out of range (0, {:d}).",
392 data[i], nodes.back()->getID());
395 elem_nodes[i] = nodes[it->second];
398 mat_ids.push_back(current_mat_id);
413 std::vector<MeshLib::Node*>& nodes,
414 std::vector<MeshLib::Element*>& elems,
415 std::map<std::size_t, std::size_t>& node_id_map,
418 if (!
parseNodes(in, nodes, node_id_map, mesh_prop))
428 while (std::getline(in, line))
431 if (str[0] ==
"ILINE")
433 parseLine(in, nodes, elems, node_id_map, mesh_prop);
440 WARN(
"GocadAsciiReader::parseLine() - Unknown keyword found: {:s}",
449 std::vector<MeshLib::Node*>
const& nodes,
450 std::vector<MeshLib::Element*>& elems,
451 std::map<std::size_t, std::size_t>
const& node_id_map,
456 int current_mat_id(0);
457 if (!mat_ids.empty())
459 current_mat_id = (*std::max_element(mat_ids.begin(), mat_ids.end()))++;
461 std::streampos pos = in.tellg();
464 while (std::getline(in, line))
470 if (line.substr(0, 4) ==
"TRGL")
472 std::stringstream sstr(line);
474 std::array<std::size_t, 3> data{};
475 sstr >> keyword >> data[0] >> data[1] >> data[2];
476 std::array<MeshLib::Node*, 3> elem_nodes{};
477 for (std::size_t i = 0; i < 3; ++i)
479 auto const it = node_id_map.find(data[i]);
480 if (it == node_id_map.end() || it->second >= nodes.size())
482 ERR(
"Error: Node ID ({:d}) out of range (0, {:d}).",
483 data[i], nodes.back()->getID());
486 elem_nodes[i] = nodes[it->second];
489 mat_ids.push_back(current_mat_id);
504 std::vector<MeshLib::Node*>& nodes,
505 std::vector<MeshLib::Element*>& elems,
506 std::map<std::size_t, std::size_t>& node_id_map,
509 if (!
parseNodes(in, nodes, node_id_map, mesh_prop))
513 if (!
parseElements(in, nodes, elems, node_id_map, mesh_prop))
519 while (std::getline(in, line))
522 if (str[0] ==
"TFACE" || str[0] ==
"3DFace")
527 if (str[0] ==
"BSTONE")
531 else if (str[0] ==
"BORDER")
535 else if (line ==
"END")
542 "GocadAsciiReader::parseSurface() - Unknown keyword found: "
554 std::string& mesh_name,
556 bool const flip_elevation)
558 std::vector<MeshLib::Node*> nodes;
559 std::vector<MeshLib::Element*> elems;
560 std::map<std::size_t, std::size_t> node_id_map;
563 return_val = parser(in, nodes, elems, node_id_map, mesh_prop);
569 std::for_each(nodes.begin(), nodes.end(),
584 std::string& mesh_name)
594 bool flip_elevation =
false;
596 while (std::getline(in, line))
603 if (str[0] ==
"GOCAD_ORIGINAL_COORDINATE_SYSTEM")
606 if (!coordinate_system.
parse(in))
608 ERR(
"Error parsing coordinate system.");
611 flip_elevation = (coordinate_system.
z_positive ==
614 else if (str[0] ==
"GEOLOGICAL_FEATURE" ||
615 str[0] ==
"GEOLOGICAL_TYPE" ||
616 str[0] ==
"STRATIGRAPHIC_POSITION" || str[0] ==
"REGION")
620 else if (str[0] ==
"PROPERTY_CLASS_HEADER")
624 ERR(
"Error parsing PROPERTY_CLASS_HEADER.");
628 else if (str[0] ==
"PROPERTIES")
632 ERR(
"Error parsing PROPERTIES");
642 (str[0] ==
"TFACE" || str[0] ==
"3DFace"))
649 WARN(
"GocadAsciiReader::readData() - Unknown keyword found: {:s}",
658 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes,
661 std::ifstream in(file_name);
664 ERR(
"GocadAsciiReader::readFile(): Could not open file {:s}.",
684 ERR(
"Parsing of type {:s} is not implemented. Skipping "
693 std::to_string(meshes.size() + 1);
694 std::unique_ptr<MeshLib::Mesh> mesh(
readData(in, type, mesh_name));
697 ERR(
"File parsing aborted...");
700 meshes.push_back(std::move(mesh));
Definition of the Line class.
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition of the class Properties that implements a container of properties.
Definition of the Mesh class.
Definition of the Node class.
Definition of the Tri class.
bool parse(std::istream &in)
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
PropertyVector< T > const * getPropertyVector(std::string_view name) const
void trim(std::string &str, char ch)
void cleanupVectorElements(std::vector< T * > &items)
std::string dropFileExtension(std::string const &filename)
std::vector< std::string > splitString(std::string const &str)
T str2number(const std::string &str)
void checkLineEndings(std::string const &file_name)
Checks if current line is a designated keyword for a GoCAD data set.
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 parseHeader(std::ifstream &in, std::string &mesh_name)
Parses the HEADER section (everything except the name is ignored right now)
const std::string mat_id_name
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 parsePropertyClass(std::ifstream &in)
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.
void checkMeshNames(std::vector< std::unique_ptr< MeshLib::Mesh > > const &meshes)
const std::string eof_error
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 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 parseAtomRegionIndicators(std::ifstream &in)
bool 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.
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::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!)
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.
DataType datasetFound(std::ifstream &in)
Checks if a GoCAD data set begins at the current stream position.
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)
MeshLib::Node * createNode(std::stringstream &sstr)
std::string dataType2String(DataType const t)
Given a Gocad DataType this returns the appropriate string.
std::string dataType2ShortString(DataType const t)
Given a Gocad DataType this returns the appropriate short form.