17#include <tclap/CmdLine.h>
23#include <QCoreApplication>
53 std::size_t
const n_intervals)
55 std::vector<GeoLib::Point*> points;
58 double const interval = length / n_intervals;
60 GeoLib::Point const vec((end[0] - start[0]), (end[1] - start[1]),
62 for (std::size_t i = 1; i < n_intervals; ++i)
65 start[0] + ((i * interval) / length * vec[0]),
66 start[1] + ((i * interval) / length * vec[1]), 0, i));
76 std::size_t
const length = points.size();
77 for (std::size_t i = 0; i < length; ++i)
87 std::vector<std::string>
const& layer_names,
90 double const resolution)
92 std::vector<std::string> geo_name_list;
93 std::size_t
const n_layers = layer_names.size();
94 for (std::size_t i = 0; i < n_layers; ++i)
96 std::unique_ptr<MeshLib::Mesh>
const layer(
100 ERR(
"Could not read file {:s}. Skipping layer...", layer_names[i]);
103 if (layer->getDimension() != 2)
105 ERR(
"Layer {:d} is not a 2D mesh. Skipping layer...", i);
109 std::string geo_name(std::to_string(i));
110 auto points(
createPoints(pnt_start, pnt_end, resolution));
114 std::vector<GeoLib::Polyline*> lines;
121 geo_name_list.push_back(geo_name);
123 return geo_name_list;
128 return ((*a)[2] < (*b)[2]) ? a : b;
135 std::vector<std::string>
const& geo_names,
136 std::string& merged_geo_name)
138 std::vector<GeoLib::Point*> points;
139 std::vector<GeoLib::Polyline*> lines;
142 std::size_t
const pnts_per_line = DEM_pnts.size();
143 std::size_t
const n_layers = geo_names.size();
144 std::vector<std::size_t> last_line_idx(pnts_per_line, 0);
146 auto layer_pnts = *geo.
getPointVec(geo_names.back());
147 for (std::size_t i = 0; i < pnts_per_line; ++i)
151 last_line_idx[i] = i;
153 for (
int j = n_layers - 2; j >= 0; --j)
156 for (std::size_t i = 0; i < pnts_per_line; ++i)
158 line->
addPoint(last_line_idx[pnts_per_line - i - 1]);
161 for (std::size_t i = 0; i < pnts_per_line; ++i)
165 std::size_t idx = last_line_idx[i];
166 if ((*points[idx])[2] < (*layer_pnts[i])[2])
172 last_line_idx[i] = idx;
178 lines.push_back(line);
181 geo.
addPointVec(std::move(points), merged_geo_name,
189 std::vector<GeoLib::Point*>& points)
192 auto const [plane_normal, d] =
195 Eigen::Matrix3d
const rotation_matrix =
200 double const z_shift =
202 std::for_each(points.begin(), points.end(),
204 return {rotation_matrix, z_shift};
212 std::string
const& output_name,
213 std::string& merged_geo_name,
214 bool const keep_gml_file)
216 std::string
const filename(output_name +
".gml");
235 std::string
const& geo_name,
236 std::string
const& output_name,
double res)
238 std::string
const gmsh_geo_name(output_name +
".geo");
239 std::vector<std::string> gmsh_geo;
240 gmsh_geo.push_back(geo_name);
243 0, gmsh_geo,
false,
false);
247 ERR(
"Writing gmsh geo file '{:s}' failed.", gmsh_geo_name);
250 std::string
const gmsh_mesh_name = output_name +
".msh";
251 std::string gmsh_command =
"gmsh -2 -algo meshadapt " + gmsh_geo_name;
252 gmsh_command +=
" -o " + gmsh_mesh_name +
" -format msh22";
253 int const return_value = std::system(gmsh_command.c_str());
254 if (return_value != 0)
256 ERR(
"Execution of gmsh command returned non-zero status, %d",
265 double const z_shift)
267 std::vector<MeshLib::Node*>
const& nodes = mesh.
getNodes();
268 std::for_each(nodes.begin(), nodes.end(),
276 std::vector<std::size_t> line_idx;
277 std::vector<MeshLib::Element*>
const& elems = mesh.
getElements();
278 std::for_each(elems.begin(), elems.end(),
281 if (e->getGeomType() == MeshLib::MeshElemType::LINE)
283 line_idx.push_back(e->getID());
286 if (line_idx.size() == mesh.getNumberOfElements())
294 std::vector<std::size_t>
const& idx_array,
295 std::string
const& file_name)
297 std::unique_ptr<MeshLib::Mesh>
const boundary(
299 if (boundary ==
nullptr)
301 ERR(
"Error extracting boundary '{:s}'", file_name);
309 std::string
const& output_name,
312 auto const edge_length = minMaxEdgeLength(mesh.
getElements());
313 double const eps = edge_length.first / 100.0;
314 std::unique_ptr<MeshLib::Mesh> boundary_mesh(
321 auto const& elems = boundary_mesh->getElements();
322 std::vector<std::size_t> left_bound_idx, right_bound_idx, top_bound_idx,
324 Eigen::Vector2d
const anchor(pnt_start[0], pnt_start[1]);
327 Eigen::Vector2d
const n1((*e->getNode(0))[0], (*e->getNode(0))[1]);
328 Eigen::Vector2d
const n2((*e->getNode(1))[0], (*e->getNode(1))[1]);
329 Eigen::Vector2d
const dist1(n1 - anchor);
330 Eigen::Vector2d
const dist2(n2 - anchor);
331 std::size_t
const id = e->getID();
333 if ((dist1 - dist2).squaredNorm() < eps)
335 top_bound_idx.push_back(
id);
336 bottom_bound_idx.push_back(
id);
338 if (dist1.squaredNorm() < eps)
340 right_bound_idx.push_back(
id);
344 left_bound_idx.push_back(
id);
349 if (dist2.squaredNorm() < dist1.squaredNorm())
351 top_bound_idx.push_back(
id);
352 left_bound_idx.push_back(
id);
353 right_bound_idx.push_back(
id);
357 bottom_bound_idx.push_back(
id);
358 left_bound_idx.push_back(
id);
359 right_bound_idx.push_back(
id);
363 writeBoundary(*boundary_mesh, left_bound_idx, output_name +
"_left");
364 writeBoundary(*boundary_mesh, right_bound_idx, output_name +
"_right");
365 writeBoundary(*boundary_mesh, top_bound_idx, output_name +
"_top");
366 writeBoundary(*boundary_mesh, bottom_bound_idx, output_name +
"_bottom");
369int main(
int argc,
char* argv[])
371 QCoreApplication a(argc, argv);
373 "Creates a triangle-mesh of a vertical slice out of a list of input "
374 "layer meshes. The slice is defined by a start- and end-point. In "
375 "addition, the resolution for meshing the extracted slice (i.e. the "
376 "maximum edge length of the domain discretisation) needs to be "
377 "specified. The utility requires access to the meshing utility GMSH to "
378 "work correctly.\n\n"
379 "OpenGeoSys-6 software, version " +
382 "Copyright (c) 2012-2024, OpenGeoSys Community "
383 "(http://www.opengeosys.org)",
385 TCLAP::SwitchArg test_arg(
"t",
"testdata",
"keep test data",
false);
387 TCLAP::SwitchArg bound_arg(
"b",
"bounds",
"save mesh boundaries",
false);
389 TCLAP::ValueArg<double> res_arg(
391 "desired edge length of triangles in the resulting slice.",
true, 0,
392 "floating point number");
394 TCLAP::ValueArg<double> end_y_arg(
395 "",
"end-y",
"y-coordinates of the end point defining the slice",
true,
396 0,
"floating point number");
398 TCLAP::ValueArg<double> end_x_arg(
399 "",
"end-x",
"x-coordinates of the end point defining the slice",
true,
400 0,
"floating point number");
402 TCLAP::ValueArg<double> start_y_arg(
403 "",
"start-y",
"y-coordinates of the start point defining the slice",
404 true, 0,
"floating point number");
405 cmd.add(start_y_arg);
406 TCLAP::ValueArg<double> start_x_arg(
407 "",
"start-x",
"x-coordinates of the start point defining the slice",
408 true, 0,
"floating point number");
409 cmd.add(start_x_arg);
410 TCLAP::ValueArg<std::string> output_arg(
411 "o",
"output",
"name of output mesh (*.vtu)",
true,
"",
"string");
413 TCLAP::ValueArg<std::string> input_arg(
415 "name of the input file list containing the paths the all input layers "
416 "in correct order from top to bottom",
419 cmd.parse(argc, argv);
422 MPI_Init(&argc, &argv);
425 std::string
const input_name = input_arg.getValue();
426 std::string
const output_name = output_arg.getValue();
429 {start_x_arg.getValue(), start_y_arg.getValue(), 0.0}};
431 {end_x_arg.getValue(), end_y_arg.getValue(), 0.0}};
434 std::size_t
const res = std::ceil(length / res_arg.getValue());
435 double const interval_length = length / res;
437 std::vector<std::string>
const layer_names =
439 if (layer_names.size() < 2)
441 ERR(
"At least two layers are required to extract a slice.");
449 std::vector<std::string>
const geo_name_list =
452 if (geo_name_list.size() < 2)
454 ERR(
"Less than two geometries could be created from layers. Aborting "
462 std::string merged_geo_name =
"merged_geometries";
464 std::vector<GeoLib::Point*> points = *geo.
getPointVec(merged_geo_name);
468 std::unique_ptr<MeshLib::Mesh> mesh(
469 generateMesh(geo, merged_geo_name, output_name, interval_length));
470 if (!test_arg.getValue())
477 ERR(
"Error generating mesh... (GMSH was unable to output mesh)");
485 if (new_mesh ==
nullptr)
487 ERR(
"Error generating mesh... (GMSH created line mesh)");
497 auto const edge_length = minMaxEdgeLength(new_mesh->getElements());
498 double const minimum_node_distance = edge_length.first / 100.0;
500 std::unique_ptr<MeshLib::Mesh> revised_mesh(
501 rev.
simplifyMesh(
"RevisedMesh", minimum_node_distance));
503 if (bound_arg.getValue())
Definition of the AABB class.
Definition of analytical geometry functions.
Definition of the Element class.
Definition of the GEOObjects class.
Definition of the Point class.
Definition of the GeoMapper class.
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition of the MeshRevision class.
Definition of the Mesh class.
Definition of the Node class.
Definition of the Point3d class.
Definition of the Polygon class.
Definition of the PolyLine class.
int main(int argc, char *argv[])
void rotateMesh(MeshLib::Mesh &mesh, Eigen::Matrix3d const &rot_mat, double const z_shift)
inverse rotation of the mesh, back into original position
void extractBoundaries(MeshLib::Mesh const &mesh, std::string const &output_name, MathLib::Point3d const &pnt_start)
std::vector< std::string > createGeometries(GeoLib::GEOObjects &geo, std::vector< std::string > const &layer_names, MathLib::Point3d const &pnt_start, MathLib::Point3d const &pnt_end, double const resolution)
creates a mapped line for each of the mesh layers
void writeBoundary(MeshLib::Mesh const &mesh, std::vector< std::size_t > const &idx_array, std::string const &file_name)
void mergeGeometries(GeoLib::GEOObjects &geo, std::vector< std::string > const &geo_names, std::string &merged_geo_name)
MeshLib::Mesh * removeLineElements(MeshLib::Mesh const &mesh)
removes line elements from mesh such that only triangles remain
GeoLib::Polyline * createPolyline(std::vector< GeoLib::Point * > const &points)
creates a polyline to be mapped on a mesh layer
std::pair< Eigen::Matrix3d, double > rotateGeometryToXY(std::vector< GeoLib::Point * > &points)
rotates the merged geometry into the XY-plane
std::vector< GeoLib::Point * > createPoints(MathLib::Point3d const &start, MathLib::Point3d const &end, std::size_t const n_intervals)
creates a vector of sampling points based on the specified resolution
static GeoLib::Point * getMinElevationPoint(GeoLib::Point *a, GeoLib::Point *b)
void consolidateGeometry(GeoLib::GEOObjects &geo, std::string const &output_name, std::string &merged_geo_name, bool const keep_gml_file)
MeshLib::Mesh * generateMesh(GeoLib::GEOObjects &geo, std::string const &geo_name, std::string const &output_name, double res)
converts geometry into GMSH format and creates mesh
Implementation of the VtuInterface class.
Definition of the XmlGmlInterface class.
std::string writeToString()
Writes the object to a string.
Reads and writes GMSH-files to and from OGS data structures.
void writePhysicalGroups(bool flag)
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
Eigen::Vector3d const & getMaxPoint() const
Eigen::Vector3d const & getMinPoint() const
Container class for geometric objects.
void addPolylineVec(std::vector< Polyline * > &&lines, std::string const &name, PolylineVec::NameIdMap &&ply_names)
const std::vector< Point * > * getPointVec(const std::string &name) const
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()))
bool removePointVec(const std::string &name)
bool removePolylineVec(const std::string &name)
Reads and writes GeoObjects to and from XML files.
int readFile(const QString &fileName) override
Reads an xml-file containing geometric object definitions into the GEOObjects used in the constructor...
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
std::size_t getPointID(std::size_t const i) const
virtual bool addPoint(std::size_t pnt_id)
std::map< std::string, std::size_t > NameIdMap
Reads and writes VtkXMLUnstructuredGrid-files (vtu) to and from OGS data structures....
bool writeToFile(std::filesystem::path const &file_path)
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
std::vector< std::string > readStringListFromFile(std::string const &filename)
Reads non-empty lines from a list of strings from a file into a vector.
int writeStringToFile(std::string_view content, std::filesystem::path const &file_path)
void removeFile(std::string const &filename)
@ FixedMeshDensity
set the parameter with a fixed value
MeshLib::Mesh * readGMSHMesh(std::string const &fname, bool const is_created_with_gmsh2)
void rotatePoints(Eigen::Matrix3d const &rot_mat, InputIterator pnts_begin, InputIterator pnts_end)
Eigen::Matrix3d computeRotationMatrixToXY(Eigen::Vector3d const &n)
std::pair< Eigen::Vector3d, double > getNewellPlane(InputIterator pnts_begin, InputIterator pnts_end)
GITINFOLIB_EXPORT const std::string ogs_version
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)
constexpr std::string_view getBulkIDString(MeshItemType mesh_item_type)
Definition of readMeshFromFile function.