28 namespace GocadAsciiReader
38 const std::string
eof_error =
"Error: Unexpected end of file.";
43 void 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)
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 else if (line.substr(0, 1) ==
"}")
168 while (std::getline(in, line))
170 if (line.substr(0, 1) ==
"}")
182 std::array<std::string, 7>
const property_keywords = {
183 {
"PROPERTY_CLASSES",
"PROP_LEGAL_RANGES",
"NO_DATA_VALUES",
184 "PROPERTY_KINDS",
"PROPERTY_SUBCLASSES",
"UNITS",
"ESIZES"}};
188 std::find(property_keywords.begin(), property_keywords.end(), str);
189 if (res != property_keywords.end())
193 return std::string(
"");
199 std::vector<std::string>
const& names,
205 std::streampos pos = in.tellg();
207 while (getline(in, line))
226 if (names.size() != prop_size.size())
228 ERR(
"Error: Number of PROPERTY-names ({:d}) does not match "
229 "number of ESIZES ({:d})",
230 names.size(), prop_size.size());
233 std::size_t
const n_names(names.size());
234 for (std::size_t i = 1; i < n_names; ++i)
239 BaseLib::str2number<std::size_t>(prop_size[i]));
253 std::array<double, 3> data{};
254 sstr >> keyword >>
id >> data[0] >> data[1] >> data[2];
263 while (std::getline(in, line))
265 if (line.substr(0, 26) ==
"END_ATOM_REGION_INDICATORS")
275 std::vector<MeshLib::Node*>& nodes,
276 std::map<std::size_t, std::size_t>& node_id_map,
280 std::streampos pos = in.tellg();
282 while (std::getline(in, line))
285 if (line.substr(0, 3) ==
"SEG" || line.substr(0, 4) ==
"TRGL")
291 if (line.substr(0, 28) ==
"BEGIN_ATOM_REGION_INDICATORS")
295 ERR(
"File ended while parsing Atom Region Indicators...");
305 if (!(line.substr(0, 4) ==
"VRTX" || line.substr(0, 5) ==
"PVRTX" ||
306 line.substr(0, 4) ==
"ATOM"))
308 WARN(
"GocadAsciiReader::parseNodes() - Unknown keyword found: {:s}",
313 std::stringstream sstr(line);
323 for (
auto [
name, property] : mesh_prop)
338 else if (line.substr(0, 4) ==
"ATOM")
343 sstr >> keyword >> new_id >> ref_id;
347 node_id_map[nodes.back()->getID()] = nodes.size() - 1;
356 std::vector<MeshLib::Node*>& nodes,
357 std::vector<MeshLib::Element*>& elems,
358 std::map<std::size_t, std::size_t>
const& node_id_map,
363 int current_mat_id(0);
364 if (!mat_ids.empty())
366 current_mat_id = (*std::max_element(mat_ids.begin(), mat_ids.end()))++;
368 std::streampos pos = in.tellg();
371 while (std::getline(in, line))
377 if (line.substr(0, 3) ==
"SEG")
379 std::stringstream sstr(line);
381 std::array<std::size_t, 2> data{};
382 sstr >> keyword >> data[0] >> data[1];
383 std::array<MeshLib::Node*, 2> elem_nodes{};
384 for (std::size_t i = 0; i < 2; ++i)
386 auto const it = node_id_map.find(data[i]);
387 if (it == node_id_map.end() || it->second >= nodes.size())
389 ERR(
"Error: Node ID ({:d}) out of range (0, {:d}).",
390 data[i], nodes.back()->getID());
393 elem_nodes[i] = nodes[it->second];
396 mat_ids.push_back(current_mat_id);
411 std::vector<MeshLib::Node*>& nodes,
412 std::vector<MeshLib::Element*>& elems,
413 std::map<std::size_t, std::size_t>& node_id_map,
416 if (!
parseNodes(in, nodes, node_id_map, mesh_prop))
426 while (std::getline(in, line))
429 if (str[0] ==
"ILINE")
431 parseLine(in, nodes, elems, node_id_map, mesh_prop);
438 WARN(
"GocadAsciiReader::parseLine() - Unknown keyword found: {:s}",
447 std::vector<MeshLib::Node*>& nodes,
448 std::vector<MeshLib::Element*>& elems,
449 std::map<std::size_t, std::size_t>
const& node_id_map,
454 int current_mat_id(0);
455 if (!mat_ids.empty())
457 current_mat_id = (*std::max_element(mat_ids.begin(), mat_ids.end()))++;
459 std::streampos pos = in.tellg();
462 while (std::getline(in, line))
468 if (line.substr(0, 4) ==
"TRGL")
470 std::stringstream sstr(line);
472 std::array<std::size_t, 3> data{};
473 sstr >> keyword >> data[0] >> data[1] >> data[2];
474 std::array<MeshLib::Node*, 3> elem_nodes{};
475 for (std::size_t i = 0; i < 3; ++i)
477 auto const it = node_id_map.find(data[i]);
478 if (it == node_id_map.end() || it->second >= nodes.size())
480 ERR(
"Error: Node ID ({:d}) out of range (0, {:d}).",
481 data[i], nodes.back()->getID());
484 elem_nodes[i] = nodes[it->second];
487 mat_ids.push_back(current_mat_id);
502 std::vector<MeshLib::Node*>& nodes,
503 std::vector<MeshLib::Element*>& elems,
504 std::map<std::size_t, std::size_t>& node_id_map,
507 if (!
parseNodes(in, nodes, node_id_map, mesh_prop))
511 if (!
parseElements(in, nodes, elems, node_id_map, mesh_prop))
517 while (std::getline(in, line))
520 if (str[0] ==
"TFACE")
525 if (str[0] ==
"BSTONE")
529 else if (str[0] ==
"BORDER")
533 else if (line ==
"END")
540 "GocadAsciiReader::parseSurface() - Unknown keyword found: "
550 template <
typename T>
552 std::string& mesh_name,
555 std::vector<MeshLib::Node*> nodes;
556 std::vector<MeshLib::Element*> elems;
557 std::map<std::size_t, std::size_t> node_id_map;
560 return_val = parser(in, nodes, elems, node_id_map, mesh_prop);
564 return new MeshLib::Mesh(mesh_name, nodes, elems, mesh_prop);
574 std::string& mesh_name)
585 while (std::getline(in, line))
592 if (str[0] ==
"GOCAD_ORIGINAL_COORDINATE_SYSTEM")
595 if (!coordinate_system.
parse(in))
597 ERR(
"Error parsing coordinate system.");
601 else if (str[0] ==
"GEOLOGICAL_FEATURE" ||
602 str[0] ==
"GEOLOGICAL_TYPE" ||
603 str[0] ==
"STRATIGRAPHIC_POSITION")
607 else if (str[0] ==
"PROPERTY_CLASS_HEADER")
611 ERR(
"Error parsing PROPERTY_CLASS_HEADER.");
615 else if (str[0] ==
"PROPERTIES")
619 ERR(
"Error parsing PROPERTIES");
633 WARN(
"GocadAsciiReader::readData() - Unknown keyword found: {:s}",
642 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes,
645 std::ifstream in(file_name);
648 ERR(
"GocadAsciiReader::readFile(): Could not open file {:s}.",
668 ERR(
"Parsing of type {:s} is not implemented. Skipping "
677 std::to_string(meshes.size() + 1);
678 std::unique_ptr<MeshLib::Mesh> mesh(
readData(in, type, mesh_name));
681 ERR(
"File parsing aborted...");
684 meshes.push_back(std::move(mesh));
Definition of the Line class.
void INFO(char const *fmt, Args const &... args)
void ERR(char const *fmt, Args const &... args)
void WARN(char const *fmt, Args const &... 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 > const * getPropertyVector(std::string const &name) const
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)
void trim(std::string &str, char ch)
std::string dropFileExtension(std::string const &filename)
std::vector< std::string > splitString(std::string const &str)
void cleanupVectorElements(std::vector< T1 * > const &items, std::vector< T2 * > const &dependent_items)
bool parseLineSegments(std::ifstream &in, std::vector< MeshLib::Node * > &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 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.
void checkLineEndings(std::string const &file_name)
Checks if current line is a designated keyword for a GoCAD data set.
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!)
bool parseHeader(std::ifstream &in, std::string &mesh_name)
Parses the HEADER section (everything except the name is ignored right now)
MeshLib::Node * createNode(std::stringstream &sstr)
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.
MeshLib::Mesh * createMesh(std::ifstream &in, DataType type, std::string &mesh_name, MeshLib::Properties &mesh_prop, T parser)
Converts parsed data into mesh.
void checkMeshNames(std::vector< std::unique_ptr< MeshLib::Mesh >> const &meshes)
const std::string eof_error
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 parseElements(std::ifstream &in, std::vector< MeshLib::Node * > &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.
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)
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)
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.