32const std::string
eof_error =
"Error: Unexpected end of file.";
37void checkMeshNames(std::vector<std::unique_ptr<MeshLib::Mesh>>
const& meshes)
39 std::size_t
const n_meshes = meshes.size();
40 for (std::size_t i = 0; i < n_meshes; ++i)
42 std::string
const& name = meshes[i]->getName();
43 for (std::size_t j = i + 1; j < n_meshes; ++j)
45 if (meshes[j]->
getName() == name)
47 std::string
const id_str = std::to_string(meshes[j]->getID());
48 meshes[i]->setName(name +
"--importID-" + id_str);
58 return (str.substr(0, 1) ==
"#");
65 while (std::getline(in, line))
87 while (std::getline(in, line))
110 ERR(
"No known identifier found...");
119 std::ifstream in(file_name);
123 std::getline(in, line);
124 if (line.back() ==
'\r')
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).",
140 while (std::getline(in, line))
142 if (line.substr(0, 5) ==
"name:")
144 mesh_name = line.substr(5, line.length() - 5);
147 std::replace(mesh_name.begin(), mesh_name.end(),
'/',
'-');
148 std::replace(mesh_name.begin(), mesh_name.end(),
'\\',
'-');
150 else if (line.substr(0, 1) ==
"}")
165 while (std::getline(in, line))
167 if (line.substr(0, 1) ==
"}")
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"}};
185 std::find(property_keywords.begin(), property_keywords.end(), str);
186 if (res != property_keywords.end())
190 return std::string(
"");
196 std::vector<std::string>
const& names,
202 std::streampos pos = in.tellg();
204 while (std::getline(in, line))
223 if (names.size() != prop_size.size())
225 ERR(
"Error: Number of PROPERTY-names ({:d}) does not match "
226 "number of ESIZES ({:d})",
227 names.size(), prop_size.size());
230 std::size_t
const n_names(names.size());
231 for (std::size_t i = 1; i < n_names; ++i)
250 std::array<double, 3> data{};
251 sstr >> keyword >>
id >> data[0] >> data[1] >> data[2];
260 while (std::getline(in, line))
262 if (line.substr(0, 26) ==
"END_ATOM_REGION_INDICATORS")
272 std::vector<MeshLib::Node*>& nodes,
273 std::map<std::size_t, std::size_t>& node_id_map,
277 std::streampos pos = in.tellg();
279 while (std::getline(in, line))
282 if (line.substr(0, 3) ==
"SEG" || line.substr(0, 4) ==
"TRGL")
288 if (line.substr(0, 28) ==
"BEGIN_ATOM_REGION_INDICATORS")
292 ERR(
"File ended while parsing Atom Region Indicators...");
302 if (!(line.substr(0, 4) ==
"VRTX" || line.substr(0, 5) ==
"PVRTX" ||
303 line.substr(0, 4) ==
"ATOM"))
305 WARN(
"GocadAsciiReader::parseNodes() - Unknown keyword found: {:s}",
310 std::stringstream sstr(line);
320 for (
auto [name, property] : mesh_prop)
335 else if (line.substr(0, 4) ==
"ATOM")
340 sstr >> keyword >> new_id >> ref_id;
341 nodes.push_back(
new MeshLib::Node(nodes[ref_id]->data(), new_id));
343 node_id_map[nodes.back()->getID()] = nodes.size() - 1;
352 std::vector<MeshLib::Node*>
const& nodes,
353 std::vector<MeshLib::Element*>& elems,
354 std::map<std::size_t, std::size_t>
const& node_id_map,
359 int current_mat_id(0);
360 if (!mat_ids.
empty())
362 current_mat_id = (*std::max_element(mat_ids.
begin(), mat_ids.
end()))++;
364 std::streampos pos = in.tellg();
367 while (std::getline(in, line))
373 if (line.substr(0, 3) ==
"SEG")
375 std::stringstream sstr(line);
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)
382 auto const it = node_id_map.find(data[i]);
383 if (it == node_id_map.end() || it->second >= nodes.size())
385 ERR(
"Error: Node ID ({:d}) out of range (0, {:d}).",
386 data[i], nodes.back()->getID());
389 elem_nodes[i] = nodes[it->second];
407 std::vector<MeshLib::Node*>& nodes,
408 std::vector<MeshLib::Element*>& elems,
409 std::map<std::size_t, std::size_t>& node_id_map,
412 if (!
parseNodes(in, nodes, node_id_map, mesh_prop))
422 while (std::getline(in, line))
425 if (str[0] ==
"ILINE")
427 parseLine(in, nodes, elems, node_id_map, mesh_prop);
434 WARN(
"GocadAsciiReader::parseLine() - Unknown keyword found: {:s}",
443 std::vector<MeshLib::Node*>
const& nodes,
444 std::vector<MeshLib::Element*>& elems,
445 std::map<std::size_t, std::size_t>
const& node_id_map,
450 int current_mat_id(0);
451 if (!mat_ids.
empty())
453 current_mat_id = (*std::max_element(mat_ids.
begin(), mat_ids.
end()))++;
455 std::streampos pos = in.tellg();
458 while (std::getline(in, line))
464 if (line.substr(0, 4) ==
"TRGL")
466 std::stringstream sstr(line);
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)
473 auto const it = node_id_map.find(data[i]);
474 if (it == node_id_map.end() || it->second >= nodes.size())
476 ERR(
"Error: Node ID ({:d}) out of range (0, {:d}).",
477 data[i], nodes.back()->getID());
480 elem_nodes[i] = nodes[it->second];
498 std::vector<MeshLib::Node*>& nodes,
499 std::vector<MeshLib::Element*>& elems,
500 std::map<std::size_t, std::size_t>& node_id_map,
503 if (!
parseNodes(in, nodes, node_id_map, mesh_prop))
507 if (!
parseElements(in, nodes, elems, node_id_map, mesh_prop))
513 while (std::getline(in, line))
516 if (str[0] ==
"TFACE" || str[0] ==
"3DFace")
521 if (str[0] ==
"BSTONE")
525 else if (str[0] ==
"BORDER")
529 else if (line ==
"END")
536 "GocadAsciiReader::parseSurface() - Unknown keyword found: "
548 std::string& mesh_name,
550 bool const flip_elevation)
552 std::vector<MeshLib::Node*> nodes;
553 std::vector<MeshLib::Element*> elems;
554 std::map<std::size_t, std::size_t> node_id_map;
557 return_val = parser(in, nodes, elems, node_id_map, mesh_prop);
563 std::for_each(nodes.begin(), nodes.end(),
578 std::string& mesh_name)
588 bool flip_elevation =
false;
590 while (std::getline(in, line))
597 if (str[0] ==
"GOCAD_ORIGINAL_COORDINATE_SYSTEM")
600 if (!coordinate_system.
parse(in))
602 ERR(
"Error parsing coordinate system.");
605 flip_elevation = (coordinate_system.
z_positive ==
608 else if (str[0] ==
"GEOLOGICAL_FEATURE" ||
609 str[0] ==
"GEOLOGICAL_TYPE" ||
610 str[0] ==
"STRATIGRAPHIC_POSITION" || str[0] ==
"REGION")
614 else if (str[0] ==
"PROPERTY_CLASS_HEADER")
618 ERR(
"Error parsing PROPERTY_CLASS_HEADER.");
622 else if (str[0] ==
"PROPERTIES")
626 ERR(
"Error parsing PROPERTIES");
636 (str[0] ==
"TFACE" || str[0] ==
"3DFace"))
643 WARN(
"GocadAsciiReader::readData() - Unknown keyword found: {:s}",
652 std::vector<std::unique_ptr<MeshLib::Mesh>>& meshes,
655 std::ifstream in(file_name);
658 ERR(
"GocadAsciiReader::readFile(): Could not open file {:s}.",
678 ERR(
"Parsing of type {:s} is not implemented. Skipping "
687 std::to_string(meshes.size() + 1);
688 std::unique_ptr<MeshLib::Mesh> mesh(
readData(in, type, mesh_name));
691 ERR(
"File parsing aborted...");
694 meshes.push_back(std::move(mesh));
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)
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
constexpr bool empty() const
constexpr PROP_VAL_TYPE * begin()
constexpr void push_back(const PROP_VAL_TYPE &value)
constexpr PROP_VAL_TYPE * end()
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.
TemplateElement< MeshLib::LineRule2 > Line
TemplateElement< MeshLib::TriRule3 > Tri