19 #include <QtXml/QDomDocument>
42 std::unique_ptr<std::vector<GeoLib::Polyline*>>
44 std::unique_ptr<std::vector<GeoLib::Surface*>>
61 : XMLQtInterface(
"OpenGeoSysGLI.xsd"), _geo_objs(geo_objs)
72 QDomDocument doc(
"OGS-GLI-DOM");
74 QDomElement docElement = doc.documentElement();
75 if (docElement.nodeName().compare(
"OpenGeoSysGLI"))
77 ERR(
"XmlGmlInterface::readFile() - Unexpected XML root.");
81 std::string gliName(
"[NN]");
83 auto points = std::make_unique<std::vector<GeoLib::Point*>>();
84 auto polylines = std::make_unique<std::vector<GeoLib::Polyline*>>();
85 auto surfaces = std::make_unique<std::vector<GeoLib::Surface*>>();
87 using MapNameId = std::map<std::string, std::size_t>;
88 auto pnt_names = std::make_unique<MapNameId>();
89 auto ply_names = std::make_unique<MapNameId>();
90 auto sfc_names = std::make_unique<MapNameId>();
92 QDomNodeList geoTypes = docElement.childNodes();
93 for (
int i = 0; i < geoTypes.count(); i++)
95 const QDomNode type_node(geoTypes.at(i));
96 const QString nodeName = type_node.nodeName();
97 if (nodeName.compare(
"name") == 0)
99 if (type_node.toElement().text().isEmpty())
101 ERR(
"XmlGmlInterface::readFile(): <name>-tag is empty.");
103 std::move(surfaces));
107 gliName = type_node.toElement().text().toStdString();
109 else if (nodeName.compare(
"points") == 0)
111 readPoints(type_node, points.get(), pnt_names.get());
114 if (pnt_names->empty())
116 pnt_names.reset(
nullptr);
119 std::move(pnt_names));
121 else if (nodeName.compare(
"polylines") == 0)
130 catch (std::runtime_error
const&)
137 if (ply_names->empty())
139 ply_names.reset(
nullptr);
142 else if (nodeName.compare(
"surfaces") == 0)
151 catch (std::runtime_error
const&)
160 if (sfc_names->empty())
162 sfc_names.reset(
nullptr);
167 if (!polylines->empty())
170 std::move(ply_names));
173 if (!surfaces->empty())
176 std::move(sfc_names));
182 std::vector<GeoLib::Point*>* points,
183 std::map<std::string, std::size_t>* pnt_names)
186 QDomElement point = pointsRoot.firstChildElement();
187 while (!point.isNull())
189 _idx_map.insert(std::pair<std::size_t, std::size_t>(
190 strtol((point.attribute(
"id")).toStdString().c_str(), &pEnd, 10),
193 point.attribute(
"y").toDouble(),
194 point.attribute(
"z").toDouble(),
195 point.attribute(
"id").toInt());
196 if (point.hasAttribute(
"name"))
198 pnt_names->insert(std::pair<std::string, std::size_t>(
199 point.attribute(
"name").toStdString(), points->size()));
202 points->push_back(p);
203 point = point.nextSiblingElement();
208 const QDomNode& polylinesRoot,
209 std::vector<GeoLib::Polyline*>* polylines,
210 std::vector<GeoLib::Point*>
const& points,
211 const std::vector<std::size_t>& pnt_id_map,
212 std::map<std::string, std::size_t>* ply_names)
214 QDomElement polyline = polylinesRoot.firstChildElement();
215 while (!polyline.isNull())
217 std::size_t
const idx = polylines->size();
220 if (polyline.hasAttribute(
"name"))
222 std::string
const ply_name(
223 polyline.attribute(
"name").toStdString());
224 std::map<std::string, std::size_t>::const_iterator it(
225 ply_names->find(ply_name));
226 if (it == ply_names->end())
229 std::pair<std::string, std::size_t>(ply_name, idx));
234 "Polyline '{:s}' exists already. Polyline {:d} will be "
235 "inserted without a name.",
240 QDomElement point = polyline.firstChildElement();
241 auto accessOrError = [
this, &polyline](
auto pt_idx)
243 auto search =
_idx_map.find(pt_idx);
246 std::string polyline_name;
247 if (polyline.hasAttribute(
"name"))
249 polyline_name = polyline.attribute(
"name").toStdString();
252 "Polyline `{:s}' contains the point id `{:d}' which is not "
253 "in the point list.",
254 polyline_name, pt_idx);
256 return search->second;
259 while (!point.isNull())
261 (*polylines)[idx]->addPoint(
262 pnt_id_map[accessOrError(point.text().toInt())]);
263 point = point.nextSiblingElement();
266 polyline = polyline.nextSiblingElement();
271 const QDomNode& surfacesRoot,
272 std::vector<GeoLib::Surface*>* surfaces,
273 std::vector<GeoLib::Point*>
const& points,
274 const std::vector<std::size_t>& pnt_id_map,
275 std::map<std::string, std::size_t>* sfc_names)
277 QDomElement surface = surfacesRoot.firstChildElement();
278 while (!surface.isNull())
282 if (surface.hasAttribute(
"name"))
284 sfc_names->insert(std::pair<std::string, std::size_t>(
285 surface.attribute(
"name").toStdString(), surfaces->size() - 1));
288 auto accessOrError = [
this, &surface](
auto pt_idx)
290 auto search =
_idx_map.find(pt_idx);
293 std::string surface_name;
294 if (surface.hasAttribute(
"name"))
296 surface_name = surface.attribute(
"name").toStdString();
299 "Surface `{:s}' contains the point id `{:d}', which is not "
300 "in the point list.",
301 surface_name, pt_idx);
303 return search->second;
306 QDomElement element = surface.firstChildElement();
307 while (!element.isNull())
310 pnt_id_map[accessOrError(element.attribute(
"p1").toInt())];
312 pnt_id_map[accessOrError(element.attribute(
"p2").toInt())];
314 pnt_id_map[accessOrError(element.attribute(
"p3").toInt())];
315 surfaces->back()->addTriangle(p1, p2, p3);
316 element = element.nextSiblingElement();
319 surface = surface.nextSiblingElement();
326 ERR(
"XmlGmlInterface::write(): No geometry specified.");
330 out <<
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n";
333 QDomDocument doc(
"OGS-GML-DOM");
334 QDomElement root = doc.createElement(
"OpenGeoSysGLI");
335 root.setAttribute(
"xmlns:ogs",
"http://www.opengeosys.org");
336 root.setAttribute(
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
338 doc.appendChild(root);
340 QDomElement geoNameTag = doc.createElement(
"name");
341 root.appendChild(geoNameTag);
342 QDomText geoNameText =
343 doc.createTextNode(QString::fromStdString(
export_name));
344 geoNameTag.appendChild(geoNameText);
347 QDomElement pointsListTag = doc.createElement(
"points");
348 root.appendChild(pointsListTag);
353 const std::vector<GeoLib::Point*>* points(pnt_vec->
getVector());
355 if (!points->empty())
357 auto const nPoints = points->size();
358 for (std::size_t i = 0; i < nPoints; i++)
360 QDomElement pointTag = doc.createElement(
"point");
361 pointTag.setAttribute(
"id", QString::number(i));
362 pointTag.setAttribute(
364 QString::number((*(*points)[i])[0],
'f',
365 std::numeric_limits<double>::digits10));
366 pointTag.setAttribute(
368 QString::number((*(*points)[i])[1],
'f',
369 std::numeric_limits<double>::digits10));
370 pointTag.setAttribute(
372 QString::number((*(*points)[i])[2],
'f',
373 std::numeric_limits<double>::digits10));
376 if (!point_name.empty())
378 pointTag.setAttribute(
"name",
379 QString::fromStdString(point_name));
382 pointsListTag.appendChild(pointTag);
387 ERR(
"XmlGmlInterface::write(): Point vector is empty, abort "
388 "writing geometry.");
394 ERR(
"XmlGmlInterface::write(): No point vector found, abort writing "
404 const std::vector<GeoLib::Polyline*>* polylines(ply_vec->
getVector());
408 if (!polylines->empty())
410 QDomElement plyListTag = doc.createElement(
"polylines");
411 root.appendChild(plyListTag);
412 auto const nPolylines = polylines->size();
413 for (std::size_t i = 0; i < nPolylines; i++)
415 QDomElement polylineTag = doc.createElement(
"polyline");
416 polylineTag.setAttribute(
"id", QString::number(i));
418 std::string ply_name;
421 polylineTag.setAttribute(
422 "name", QString::fromStdString(ply_name));
426 ply_name = std::to_string(i);
427 polylineTag.setAttribute(
428 "name", QString::fromStdString(ply_name));
431 plyListTag.appendChild(polylineTag);
433 auto const nPoints = (*polylines)[i]->getNumberOfPoints();
434 for (std::size_t j = 0; j < nPoints; j++)
436 QDomElement plyPointTag = doc.createElement(
"pnt");
437 polylineTag.appendChild(plyPointTag);
438 QDomText plyPointText = doc.createTextNode(
439 QString::number(((*polylines)[i])->getPointID(j)));
440 plyPointTag.appendChild(plyPointText);
447 "XmlGmlInterface::write(): Polyline vector is empty, no "
448 "polylines written to file.");
455 "XmlGmlInterface::write(): Polyline vector is empty, no polylines "
463 const std::vector<GeoLib::Surface*>* surfaces(sfc_vec->
getVector());
467 if (!surfaces->empty())
469 QDomElement sfcListTag = doc.createElement(
"surfaces");
470 root.appendChild(sfcListTag);
471 auto const nSurfaces = surfaces->size();
472 for (std::size_t i = 0; i < nSurfaces; i++)
474 QDomElement surfaceTag = doc.createElement(
"surface");
475 surfaceTag.setAttribute(
"id", QString::number(i));
477 std::string sfc_name;
480 surfaceTag.setAttribute(
481 "name", QString::fromStdString(sfc_name));
484 sfcListTag.appendChild(surfaceTag);
487 std::size_t nElements =
488 ((*surfaces)[i])->getNumberOfTriangles();
489 for (std::size_t j = 0; j < nElements; j++)
491 QDomElement elementTag = doc.createElement(
"element");
492 elementTag.setAttribute(
493 "p1", QString::number((*(*(*surfaces)[i])[j])[0]));
494 elementTag.setAttribute(
495 "p2", QString::number((*(*(*surfaces)[i])[j])[1]));
496 elementTag.setAttribute(
497 "p3", QString::number((*(*(*surfaces)[i])[j])[2]));
498 surfaceTag.appendChild(elementTag);
505 "XmlGmlInterface::write(): Surface vector is empty, no "
506 "surfaces written to file.");
513 "XmlGmlInterface::write(): Surface vector is empty, no surfaces "
517 std::string xml = doc.toString().toStdString();
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 XmlGmlInterface class.
std::ostringstream out
The stream to write to.
QByteArray const & getContent() const
Container class for geometric objects.
void addSurfaceVec(std::unique_ptr< std::vector< Surface * >> sfc, const std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> sfc_names=nullptr)
const std::vector< Point * > * getPointVec(const std::string &name) const
const PointVec * getPointVecObj(const std::string &name) const
bool removePointVec(const std::string &name)
void addPointVec(std::unique_ptr< std::vector< Point * >> points, std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> pnt_id_name_map=nullptr, double eps=std::sqrt(std::numeric_limits< double >::epsilon()))
SurfaceVec * getSurfaceVecObj(const std::string &name)
Returns the surface vector with the given name.
const PolylineVec * getPolylineVecObj(const std::string &name) const
void addPolylineVec(std::unique_ptr< std::vector< Polyline * >> lines, const std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> ply_names=nullptr)
bool removePolylineVec(const std::string &name)
std::map< std::size_t, std::size_t > _idx_map
bool write() override
Writes the object to the internal stream. This method must be implemented by a subclass....
GeoLib::GEOObjects & _geo_objs
void readPoints(const QDomNode &pointsRoot, std::vector< GeoLib::Point * > *points, std::map< std::string, std::size_t > *pnt_names)
Reads GeoLib::Point-objects from an xml-file.
void readPolylines(const QDomNode &polylinesRoot, std::vector< GeoLib::Polyline * > *polylines, std::vector< GeoLib::Point * > const &points, const std::vector< std::size_t > &pnt_id_map, std::map< std::string, std::size_t > *ply_names)
Reads GeoLib::Polyline-objects from an xml-file.
void readSurfaces(const QDomNode &surfacesRoot, std::vector< GeoLib::Surface * > *surfaces, std::vector< GeoLib::Point * > const &points, const std::vector< std::size_t > &pnt_id_map, std::map< std::string, std::size_t > *sfc_names)
Reads GeoLib::Surface-objects from an xml-file.
XmlGmlInterface(GeoLib::GEOObjects &geo_objs)
int readFile(const QString &fileName) override
Reads an xml-file containing geometric object definitions into the GEOObjects used in the constructor...
This class manages pointers to Points in a std::vector along with a name. It also handles the deletin...
const std::vector< std::size_t > & getIDMap() const
std::string const & getItemNameByID(std::size_t id) const
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
A Surface is represented by Triangles. It consists of a reference to a vector of (pointers to) points...
The class TemplateVec takes a unique name and manages a std::vector of pointers to data elements of t...
const std::vector< T * > * getVector() const
bool getNameOfElementByID(std::size_t id, std::string &element_name) const
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.
TemplateElement< PointRule1 > Point
void deleteGeometry(std::unique_ptr< std::vector< GeoLib::Point * >> points, std::unique_ptr< std::vector< GeoLib::Polyline * >> polylines, std::unique_ptr< std::vector< GeoLib::Surface * >> surfaces)
void deleteSurfaces(std::unique_ptr< std::vector< GeoLib::Surface * >> surfaces)
void deletePolylines(std::unique_ptr< std::vector< GeoLib::Polyline * >> polylines)