OGS
FEFLOWGeoInterface.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <QDomElement>
7#include <QString>
8#include <QtXml/QDomDocument>
9#include <boost/algorithm/string/trim.hpp>
10#include <cctype>
11#include <fstream>
12#include <memory>
13
14#include "BaseLib/FileTools.h"
15#include "BaseLib/Logging.h"
16#include "BaseLib/StringTools.h"
17#include "GeoLib/GEOObjects.h"
18#include "GeoLib/Point.h"
19#include "GeoLib/Polygon.h"
20
21namespace FileIO
22{
23void FEFLOWGeoInterface::readFEFLOWFile(const std::string& filename,
24 GeoLib::GEOObjects& geo_objects)
25{
26 std::ifstream in(filename.c_str());
27 if (!in)
28 {
29 ERR("FEFLOWGeoInterface::readFEFLOWFile(): Could not open file {:s}.",
30 filename);
31 return;
32 }
33
34 unsigned dimension = 0;
35 std::vector<GeoLib::Point*> points;
36 std::vector<GeoLib::Polyline*> lines;
37
38 bool isXZplane = false;
39
40 std::string line_string;
41 std::stringstream line_stream;
42 while (!in.eof())
43 {
44 std::getline(in, line_string);
45 //....................................................................
46 // CLASS: the version number follows afterward, e.g. CLASS (v.5.313)
47 if (line_string.find("CLASS") != std::string::npos)
48 {
49 std::getline(in, line_string);
50 line_stream.str(line_string);
51 // problem class, time mode, problem orientation, dimension, ...
52 unsigned dummy = 0;
53 for (int i = 0; i < 3; i++)
54 {
55 line_stream >> dummy;
56 }
57 line_stream >> dimension;
58 line_stream.clear();
59 }
60 //....................................................................
61 // GRAVITY
62 else if (line_string == "GRAVITY")
63 {
64 std::getline(in, line_string);
65 line_stream.str(line_string);
66 double vec[3] = {};
67 line_stream >> vec[0] >> vec[1] >> vec[2];
68 if (vec[0] == 0.0 && vec[1] == -1.0 && vec[2] == 0.0)
69 {
70 // x-z plane
71 isXZplane = true;
72 }
73 line_stream.clear();
74 }
75 //....................................................................
76 // SUPERMESH
77 else if (line_string == "SUPERMESH")
78 {
79 readSuperMesh(in, dimension, points, lines);
80 }
81 //....................................................................
82 }
83 in.close();
84
85 if (isXZplane && !points.empty())
86 {
87 for (auto* pt : points)
88 {
89 (*pt)[2] = (*pt)[1];
90 (*pt)[1] = .0;
91 }
92 }
93 std::string project_name(
95 if (!points.empty())
96 {
97 geo_objects.addPointVec(std::move(points), project_name,
99 }
100 if (!lines.empty())
101 {
102 geo_objects.addPolylineVec(std::move(lines), project_name,
104 }
105}
106
107void FEFLOWGeoInterface::readPoints(QDomElement& nodesEle,
108 const std::string& tag,
109 int dim,
110 std::vector<GeoLib::Point*>& points)
111{
112 QDomElement xmlEle =
113 nodesEle.firstChildElement(QString::fromStdString(tag));
114 if (xmlEle.isNull())
115 {
116 return;
117 }
118 QString str_pt_list1 = xmlEle.text();
119 std::istringstream ss(str_pt_list1.toStdString());
120 std::string line_str;
121 while (!ss.eof())
122 {
123 std::getline(ss, line_str);
124 boost::trim_right(line_str);
125 if (line_str.empty())
126 {
127 continue;
128 }
129 std::istringstream line_ss(line_str);
130 std::size_t pt_id = 0;
131 std::array<double, 3> pt_xyz;
132 line_ss >> pt_id;
133 for (int i = 0; i < dim; i++)
134 {
135 line_ss >> pt_xyz[i];
136 }
137 points[pt_id - 1] = new GeoLib::Point(pt_xyz, pt_id);
138 }
139}
140
142 unsigned dimension,
143 std::vector<GeoLib::Point*>& points,
144 std::vector<GeoLib::Polyline*>& lines)
145{
146 // get XML strings
147 std::ostringstream oss;
148 std::string line_string;
149 while (true)
150 {
151 std::getline(in, line_string);
152 BaseLib::trim(line_string);
153 oss << line_string << "\n";
154 if (line_string.find("</supermesh>") != std::string::npos)
155 {
156 break;
157 }
158 }
159 const QString strXML(oss.str().c_str());
160
161 // convert string to XML
162 QDomDocument doc;
163 if (!doc.setContent(strXML))
164 {
165 ERR("FEFLOWGeoInterface::readSuperMesh(): Illegal XML format error");
166 return;
167 }
168
169 // get geometry data from XML
170 QDomElement docElem = doc.documentElement(); // #supermesh
171 // #nodes
172 QDomElement nodesEle = docElem.firstChildElement("nodes");
173 if (nodesEle.isNull())
174 {
175 return;
176 }
177
178 {
179 const QString str = nodesEle.attribute("count");
180 const long n_points = str.toLong();
181 points.resize(n_points);
182 // fixed
183 readPoints(nodesEle, "fixed", dimension, points);
184 readPoints(nodesEle, "linear", dimension, points);
185 readPoints(nodesEle, "parabolic", dimension, points);
186 }
187
188 // #polygons
189 QDomElement polygonsEle = docElem.firstChildElement("polygons");
190 if (polygonsEle.isNull())
191 {
192 return;
193 }
194
195 {
196 QDomNode child = polygonsEle.firstChild();
197 while (!child.isNull())
198 {
199 if (child.nodeName() != "polygon")
200 {
201 child = child.nextSibling();
202 continue;
203 }
204 QDomElement xmlEle = child.firstChildElement("nodes");
205 if (xmlEle.isNull())
206 {
207 continue;
208 }
209 const QString str = xmlEle.attribute("count");
210 const std::size_t n_points = str.toLong();
211 QString str_ptId_list = xmlEle.text().simplified();
212 {
213 auto* line = new GeoLib::Polyline(points);
214 lines.push_back(line);
215 std::istringstream ss(str_ptId_list.toStdString());
216 for (std::size_t i = 0; i < n_points; i++)
217 {
218 int pt_id = 0;
219 ss >> pt_id;
220 line->addPoint(pt_id - 1);
221 }
222 line->addPoint(line->getPointID(0));
223 }
224 child = child.nextSibling();
225 }
226 }
227}
228
229} // namespace FileIO
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
static void readPoints(QDomElement &nodesEle, const std::string &tag, int dim, std::vector< GeoLib::Point * > &points)
void readFEFLOWFile(const std::string &filename, GeoLib::GEOObjects &geo_objects)
static void readSuperMesh(std::ifstream &in, unsigned dimension, std::vector< GeoLib::Point * > &points, std::vector< GeoLib::Polyline * > &lines)
Container class for geometric objects.
Definition GEOObjects.h:46
void addPolylineVec(std::vector< Polyline * > &&lines, std::string const &name, PolylineVec::NameIdMap &&ply_names)
void addPointVec(std::vector< Point * > &&points, std::string &name, PointVec::NameIdMap &&pnt_id_name_map, double const eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition Polyline.h:29
std::map< std::string, std::size_t > NameIdMap
Definition TemplateVec.h:30
void trim(std::string &str, char ch)
std::string extractBaseNameWithoutExtension(std::string const &pathname)