26{
27 TCLAP::CmdLine cmd(
28 "Creates a boundary representation for a layered 3D mesh in "
29 "*.smesh-format. This boundary representation can be used with the "
30 "TetGen Tetrahedral Mesh Generator to create 3D meshes of the given "
31 "geometry at arbitrary resolutions and with varying properties. "
32 "Details on command line switches and possible parametrisation can be "
33 "found in the TetGen User's Manual. Supported raster formats are "
34 "ArcGIS ascii rasters (*.asc), Surfer Grids (*.grd) and XYZ raster "
35 "files (*.xyz)."
36 "Only input meshes consisting of line and triangle elements are "
37 "currently supported as mapping of quads might result in invalid mesh "
38 "elements.\n\n"
39 "OpenGeoSys-6 software, version " +
41 ".\n"
42 "Copyright (c) 2012-2026, OpenGeoSys Community "
43 "(http://www.opengeosys.org)",
45
46 TCLAP::SwitchArg use_ascii_arg("", "ascii_output",
47 "Write VTU output in ASCII format.");
48 cmd.add(use_ascii_arg);
49
50 double min_thickness(std::numeric_limits<double>::epsilon());
51 TCLAP::ValueArg<double> min_thickness_arg(
52 "t", "thickness",
53 "The minimum thickness of a layer to be integrated at any given "
54 "location (min = 0)",
55 false, min_thickness, "MIN_THICKNESS");
56 cmd.add(min_thickness_arg);
57
58 TCLAP::ValueArg<std::string> raster_path_arg(
59 "r", "raster-list",
60 "Input (.vtu). An ascii-file containing a list of raster files, "
61 "starting from top "
62 "(DEM) to bottom.",
63 true, "", "INPUT_FILE_LIST");
64 cmd.add(raster_path_arg);
65
66 TCLAP::ValueArg<std::string> mesh_out_arg(
67 "o", "output-mesh-file",
68 "Output (.smesh). The file name of the resulting 3D mesh", true, "",
69 "OUTPUT_FILE");
70 cmd.add(mesh_out_arg);
71
72 TCLAP::ValueArg<std::string> mesh_arg(
73 "i", "input-mesh-file",
74 "Input (.vtu | .msh). The file name of the 2D input mesh", true, "",
75 "INPUT_FILE");
76 cmd.add(mesh_arg);
77
79 cmd.add(log_level_arg);
80
81 cmd.parse(argc, argv);
82
85
86 if (min_thickness_arg.isSet())
87 {
88 min_thickness = min_thickness_arg.getValue();
89 if (min_thickness < 0)
90 {
91 ERR(
"Minimum layer thickness must be non-negative value.");
92 return EXIT_FAILURE;
93 }
94 }
95
96 INFO(
"Reading mesh '{:s}' ... ", mesh_arg.getValue());
98 mesh_arg.getValue(), true ));
99 if (!sfc_mesh)
100 {
101 ERR(
"Error reading mesh '{:s}'.", mesh_arg.getValue());
102 return EXIT_FAILURE;
103 }
104 if (sfc_mesh->getDimension() != 2)
105 {
106 ERR(
"Input mesh must be a 2D mesh.");
107 return EXIT_FAILURE;
108 }
110
111 std::vector<std::string> raster_paths =
113 if (raster_paths.size() < 2)
114 {
115 ERR(
"At least two raster files needed to create 3D mesh.");
116 return EXIT_FAILURE;
117 }
118 std::reverse(raster_paths.begin(), raster_paths.end());
119
120 std::string output_name(mesh_out_arg.getValue());
122 {
123 output_name.append(".smesh");
124 }
125
128 if (rasters)
129 {
130 if (!lv.
createLayers(*sfc_mesh, *rasters, min_thickness))
131 {
132 ERR(
"Creating the layers was erroneous.");
133 return EXIT_FAILURE;
134 }
135 }
136 else
137 {
138 ERR(
"The raster files are not accessible.");
139 return EXIT_FAILURE;
140 }
141 std::unique_ptr<MeshLib::Mesh> tg_mesh =
142 lv.
getMesh(
"BoundaryRepresentation");
143 if (tg_mesh != nullptr)
144 {
148 INFO(
"Smesh was successfully written.");
149 }
150 else
151 {
152 ERR(
"The tetgen-smesh could not be created.");
153 return EXIT_FAILURE;
154 }
155
156 return EXIT_SUCCESS;
157}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
static bool writeTetGenSmesh(const std::string &file_name, const GeoLib::GEOObjects &geo_objects, const std::string &geo_name, const std::vector< GeoLib::Point > &attribute_points)
virtual bool createLayers(MeshLib::Mesh const &mesh, std::vector< GeoLib::Raster const * > const &rasters, double minimum_thickness, double noDataReplacementValue=0.0) final
std::unique_ptr< MeshLib::Mesh > getMesh(std::string const &mesh_name) const
Returns a mesh of the subsurface representation.
Creates a volume geometry from 2D mesh layers based on raster data.
std::vector< MeshLib::Node > getAttributePoints() const
std::vector< std::string > readStringListFromFile(std::string const &filename)
Reads non-empty lines from a list of strings from a file into a vector.
TCLAP::ValueArg< std::string > makeLogLevelArg()
void initOGSLogger(std::string const &log_level)
bool hasFileExtension(std::string const &extension, std::string const &filename)
std::optional< std::vector< GeoLib::Raster const * > > readRasters(std::vector< std::string > const &raster_paths)
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)