4#include <tclap/CmdLine.h>
6#include <QCoreApplication>
44 std::size_t
const n_intervals)
46 std::vector<GeoLib::Point*> points;
49 double const interval = length / n_intervals;
51 GeoLib::Point const vec((end[0] - start[0]), (end[1] - start[1]),
53 for (std::size_t i = 1; i < n_intervals; ++i)
56 start[0] + ((i * interval) / length * vec[0]),
57 start[1] + ((i * interval) / length * vec[1]), 0, i));
67 std::size_t
const length = points.size();
68 for (std::size_t i = 0; i < length; ++i)
78 std::vector<std::string>
const& layer_names,
81 double const resolution)
83 std::vector<std::string> geo_name_list;
84 std::size_t
const n_layers = layer_names.size();
85 for (std::size_t i = 0; i < n_layers; ++i)
87 std::unique_ptr<MeshLib::Mesh>
const layer(
91 ERR(
"Could not read file {:s}. Skipping layer...", layer_names[i]);
94 if (layer->getDimension() != 2)
96 ERR(
"Layer {:d} is not a 2D mesh. Skipping layer...", i);
100 std::string geo_name(std::to_string(i));
101 auto points(
createPoints(pnt_start, pnt_end, resolution));
105 std::vector<GeoLib::Polyline*> lines;
112 geo_name_list.push_back(geo_name);
114 return geo_name_list;
119 return ((*a)[2] < (*b)[2]) ? a : b;
126 std::vector<std::string>
const& geo_names,
127 std::string& merged_geo_name)
129 std::vector<GeoLib::Point*> points;
130 std::vector<GeoLib::Polyline*> lines;
133 std::size_t
const pnts_per_line = DEM_pnts.size();
134 std::size_t
const n_layers = geo_names.size();
135 std::vector<std::size_t> last_line_idx(pnts_per_line, 0);
137 auto layer_pnts = *geo.
getPointVec(geo_names.back());
138 for (std::size_t i = 0; i < pnts_per_line; ++i)
142 last_line_idx[i] = i;
144 for (
int j = n_layers - 2; j >= 0; --j)
147 for (std::size_t i = 0; i < pnts_per_line; ++i)
149 line->
addPoint(last_line_idx[pnts_per_line - i - 1]);
152 for (std::size_t i = 0; i < pnts_per_line; ++i)
156 std::size_t idx = last_line_idx[i];
157 if ((*points[idx])[2] < (*layer_pnts[i])[2])
163 last_line_idx[i] = idx;
169 lines.push_back(line);
172 geo.
addPointVec(std::move(points), merged_geo_name,
180 std::vector<GeoLib::Point*>& points)
183 auto const [plane_normal, d] =
186 Eigen::Matrix3d
const rotation_matrix =
191 double const z_shift =
193 std::for_each(points.begin(), points.end(),
195 return {rotation_matrix, z_shift};
203 std::string
const& output_name,
204 std::string& merged_geo_name,
205 bool const keep_gml_file)
207 std::string
const filename(output_name +
".gml");
226 std::string
const& geo_name,
227 std::string
const& output_name,
double res)
229 std::string
const gmsh_geo_name(output_name +
".geo");
230 std::vector<std::string> gmsh_geo;
231 gmsh_geo.push_back(geo_name);
234 0, gmsh_geo,
false,
false);
238 ERR(
"Writing gmsh geo file '{:s}' failed.", gmsh_geo_name);
241 std::string
const gmsh_mesh_name = output_name +
".msh";
242 std::string gmsh_command =
"gmsh -2 -algo meshadapt " + gmsh_geo_name;
243 gmsh_command +=
" -o " + gmsh_mesh_name +
" -format msh22";
244 int const return_value = std::system(gmsh_command.c_str());
245 if (return_value != 0)
247 ERR(
"Execution of gmsh command returned non-zero status, %d",
256 double const z_shift)
258 std::vector<MeshLib::Node*>
const& nodes = mesh.
getNodes();
259 std::for_each(nodes.begin(), nodes.end(),
267 std::vector<std::size_t> line_idx;
268 std::vector<MeshLib::Element*>
const& elems = mesh.
getElements();
269 std::for_each(elems.begin(), elems.end(),
272 if (e->getGeomType() == MeshLib::MeshElemType::LINE)
274 line_idx.push_back(e->getID());
277 if (line_idx.size() == mesh.getNumberOfElements())
285 std::vector<std::size_t>
const& idx_array,
286 std::string
const& file_name)
288 std::unique_ptr<MeshLib::Mesh>
const boundary(
290 if (boundary ==
nullptr)
292 ERR(
"Error extracting boundary '{:s}'", file_name);
300 std::string
const& output_name,
303 auto const edge_length = minMaxEdgeLength(mesh.
getElements());
304 double const eps = edge_length.first / 100.0;
305 std::unique_ptr<MeshLib::Mesh> boundary_mesh(
312 auto const& elems = boundary_mesh->getElements();
313 std::vector<std::size_t> left_bound_idx, right_bound_idx, top_bound_idx,
315 Eigen::Vector2d
const anchor(pnt_start[0], pnt_start[1]);
318 Eigen::Vector2d
const n1((*e->getNode(0))[0], (*e->getNode(0))[1]);
319 Eigen::Vector2d
const n2((*e->getNode(1))[0], (*e->getNode(1))[1]);
320 Eigen::Vector2d
const dist1(n1 - anchor);
321 Eigen::Vector2d
const dist2(n2 - anchor);
322 std::size_t
const id = e->getID();
324 if ((dist1 - dist2).squaredNorm() < eps)
326 top_bound_idx.push_back(
id);
327 bottom_bound_idx.push_back(
id);
329 if (dist1.squaredNorm() < eps)
331 right_bound_idx.push_back(
id);
335 left_bound_idx.push_back(
id);
340 if (dist2.squaredNorm() < dist1.squaredNorm())
342 top_bound_idx.push_back(
id);
343 left_bound_idx.push_back(
id);
344 right_bound_idx.push_back(
id);
348 bottom_bound_idx.push_back(
id);
349 left_bound_idx.push_back(
id);
350 right_bound_idx.push_back(
id);
354 writeBoundary(*boundary_mesh, left_bound_idx, output_name +
"_left");
355 writeBoundary(*boundary_mesh, right_bound_idx, output_name +
"_right");
356 writeBoundary(*boundary_mesh, top_bound_idx, output_name +
"_top");
357 writeBoundary(*boundary_mesh, bottom_bound_idx, output_name +
"_bottom");
360int main(
int argc,
char* argv[])
362 QCoreApplication a(argc, argv);
364 "Creates a triangle-mesh of a vertical slice out of a list of input "
365 "layer meshes. The slice is defined by a start- and end-point. In "
366 "addition, the resolution for meshing the extracted slice (i.e. the "
367 "maximum edge length of the domain discretisation) needs to be "
368 "specified. The utility requires access to the meshing utility GMSH to "
369 "work correctly.\n\n"
370 "OpenGeoSys-6 software, version " +
373 "Copyright (c) 2012-2026, OpenGeoSys Community "
374 "(http://www.opengeosys.org)",
376 TCLAP::SwitchArg test_arg(
"t",
"testdata",
"keep test data",
false);
378 TCLAP::SwitchArg bound_arg(
"b",
"bounds",
"save mesh boundaries",
false);
380 TCLAP::ValueArg<double> res_arg(
382 "desired edge length of triangles in the resulting slice, (min = 0)",
383 true, 0,
"RESOLUTION");
385 TCLAP::ValueArg<double> end_y_arg(
386 "",
"end-y",
"y-coordinates of the end point defining the slice",
true,
389 TCLAP::ValueArg<double> end_x_arg(
390 "",
"end-x",
"x-coordinates of the end point defining the slice",
true,
393 TCLAP::ValueArg<double> start_y_arg(
394 "",
"start-y",
"y-coordinates of the start point defining the slice",
396 cmd.add(start_y_arg);
397 TCLAP::ValueArg<double> start_x_arg(
398 "",
"start-x",
"x-coordinates of the start point defining the slice",
400 cmd.add(start_x_arg);
401 TCLAP::ValueArg<std::string> output_arg(
402 "o",
"output",
"Output (.vtu). Name of output mesh file",
true,
"",
405 TCLAP::ValueArg<std::string> input_arg(
407 "Input (.vtu | .msh). Name of the input file list containing the paths "
408 "the all input layers "
409 "in correct order from top to bottom",
410 true,
"",
"INPUT_FILE_LIST");
413 cmd.add(log_level_arg);
414 cmd.parse(argc, argv);
419 std::string
const input_name = input_arg.getValue();
420 std::string
const output_name = output_arg.getValue();
423 {start_x_arg.getValue(), start_y_arg.getValue(), 0.0}};
425 {end_x_arg.getValue(), end_y_arg.getValue(), 0.0}};
428 std::size_t
const res = std::ceil(length / res_arg.getValue());
429 double const interval_length = length / res;
431 std::vector<std::string>
const layer_names =
433 if (layer_names.size() < 2)
435 ERR(
"At least two layers are required to extract a slice.");
440 std::vector<std::string>
const geo_name_list =
443 if (geo_name_list.size() < 2)
445 ERR(
"Less than two geometries could be created from layers. Aborting "
450 std::string merged_geo_name =
"merged_geometries";
452 std::vector<GeoLib::Point*> points = *geo.
getPointVec(merged_geo_name);
456 std::unique_ptr<MeshLib::Mesh> mesh(
457 generateMesh(geo, merged_geo_name, output_name, interval_length));
458 if (!test_arg.getValue())
465 ERR(
"Error generating mesh... (GMSH was unable to output mesh)");
470 if (new_mesh ==
nullptr)
472 ERR(
"Error generating mesh... (GMSH created line mesh)");
479 auto const edge_length = minMaxEdgeLength(new_mesh->getElements());
480 double const minimum_node_distance = edge_length.first / 100.0;
482 std::unique_ptr<MeshLib::Mesh> revised_mesh(
483 rev.
simplifyMesh(
"RevisedMesh", minimum_node_distance));
485 if (bound_arg.getValue())
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
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
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)
TCLAP::ValueArg< std::string > makeLogLevelArg()
void removeFile(std::string const &filename)
void initOGSLogger(std::string const &log_level)
@ 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)