83{
84 TCLAP::CmdLine cmd(
85 "Removes mesh elements based on element type, element volume, scalar "
86 "arrays, or bounding box . The documentation is available at "
87 "https://docs.opengeosys.org/docs/tools/meshing/"
88 "remove-mesh-elements.\n\n"
89 "OpenGeoSys-6 software, version " +
91 ".\n"
92 "Copyright (c) 2012-2025, OpenGeoSys Community "
93 "(http://www.opengeosys.org)",
95
96
97 TCLAP::SwitchArg invert_bounding_box_arg(
98 "", "invert", "inverts the specified bounding box", false);
99 cmd.add(invert_bounding_box_arg);
100 TCLAP::ValueArg<double> zLargeArg(
101 "", "z-max", "largest allowed extent in z-dimension", false,
102 std::numeric_limits<double>::max(), "MAX_EXTENT_Z");
103 cmd.add(zLargeArg);
104 TCLAP::ValueArg<double> zSmallArg(
105 "", "z-min", "smallest allowed extent in z-dimension", false,
106 -1 * std::numeric_limits<double>::max(), "MIN_EXTENT_Z");
107 cmd.add(zSmallArg);
108 TCLAP::ValueArg<double> yLargeArg(
109 "", "y-max", "largest allowed extent in y-dimension", false,
110 std::numeric_limits<double>::max(), "MAX_EXTENT_Y");
111 cmd.add(yLargeArg);
112 TCLAP::ValueArg<double> ySmallArg(
113 "", "y-min", "smallest allowed extent in y-dimension", false,
114 -1 * std::numeric_limits<double>::max(), "MIN_EXTENT_Y");
115 cmd.add(ySmallArg);
116 TCLAP::ValueArg<double> xLargeArg(
117 "", "x-max", "largest allowed extent in x-dimension", false,
118 std::numeric_limits<double>::max(), "MAX_EXTENT_X");
119 cmd.add(xLargeArg);
120 TCLAP::ValueArg<double> xSmallArg(
121 "", "x-min", "smallest allowed extent in x-dimension", false,
122 -1 * std::numeric_limits<double>::max(), "MIN_EXTENT_X");
123 cmd.add(xSmallArg);
124
125
126 TCLAP::SwitchArg zveArg("z", "zero-volume", "remove zero volume elements",
127 false);
128 cmd.add(zveArg);
129
130 std::vector<std::string> allowed_ele_types{
131 "point", "line", "tri", "quad", "hex", "prism", "tet", "pyramid"};
132 TCLAP::ValuesConstraint<std::string> allowedVals{allowed_ele_types};
133 TCLAP::MultiArg<std::string> eleTypeArg(
134 "t", "element-type", "element type to be removed", false, &allowedVals);
135 cmd.add(eleTypeArg);
136
137
138 TCLAP::ValueArg<std::string> property_name_arg(
139 "n", "property-name", "name of property in the mesh", false,
140 "MaterialIDs", "PROPERTY_NAME");
141 cmd.add(property_name_arg);
142
143 TCLAP::MultiArg<int> property_arg(
144 "", "property-value", "value of selected property to be removed", false,
145 "PROPERTY_VALUE");
146 cmd.add(property_arg);
147
148 TCLAP::ValueArg<double> min_property_arg(
149 "", "min-value", "minimum value of range for selected property", false,
150 0, "MIN_RANGE");
151 cmd.add(min_property_arg);
152
153 TCLAP::ValueArg<double> max_property_arg(
154 "", "max-value", "maximum value of range for selected property", false,
155 0, "MAX_RANGE");
156 cmd.add(max_property_arg);
157
158 TCLAP::SwitchArg outside_property_arg(
159 "", "outside", "remove all elements outside the given property range");
160 cmd.add(outside_property_arg);
161
162 TCLAP::SwitchArg inside_property_arg(
163 "", "inside", "remove all elements inside the given property range");
164 cmd.add(inside_property_arg);
165
166
167 TCLAP::ValueArg<std::string> mesh_out(
168 "o", "mesh-output-file",
169 "Output (.vtu). The name of the file the mesh will be written to", true,
170 "", "OUTPUT_FILE");
171 cmd.add(mesh_out);
172 TCLAP::ValueArg<std::string> mesh_in(
173 "i", "mesh-input-file",
174 "Input (.vtu). The name of the file containing the input mesh", true,
175 "", "INPUT_FILE");
176 cmd.add(mesh_in);
177 cmd.parse(argc, argv);
178
180
181 std::unique_ptr<MeshLib::Mesh const> mesh(
183 if (mesh == nullptr)
184 {
185 return EXIT_FAILURE;
186 }
187
188 INFO(
"Mesh read: {:d} nodes, {:d} elements.", mesh->getNumberOfNodes(),
189 mesh->getNumberOfElements());
191
192
193 if (zveArg.isSet())
194 {
195 INFO(
"{:d} zero volume elements found.", searcher.searchByContent());
196 }
197 if (eleTypeArg.isSet())
198 {
199 const std::vector<std::string> eleTypeNames = eleTypeArg.getValue();
200 for (const auto& typeName : eleTypeNames)
201 {
205 {
206 continue;
207 }
208 INFO(
"{:d} {:s} elements found.",
209 searcher.searchByElementType(type), typeName);
210 }
211 }
212
213 if (property_name_arg.isSet() || property_arg.isSet() ||
214 min_property_arg.isSet() || max_property_arg.isSet())
215 {
216 if ((property_arg.isSet() || min_property_arg.isSet() ||
217 max_property_arg.isSet()) &&
218 !property_name_arg.isSet())
219 {
220 ERR(
"Specify a property name for the value/range selected.");
221 return EXIT_FAILURE;
222 }
223
224 if (property_name_arg.isSet() &&
225 !((min_property_arg.isSet() && max_property_arg.isSet()) ||
226 property_arg.isSet()))
227 {
228 ERR(
"Specify a value or range ('-min-value' and '-max_value') for "
229 "the property selected.");
230 return EXIT_FAILURE;
231 }
232
233
234 if (property_arg.isSet() && property_name_arg.isSet())
235 {
237 property_arg.getValue(), searcher);
238 }
239
240
241 if (property_name_arg.isSet() && min_property_arg.isSet() &&
242 max_property_arg.isSet())
243 {
244 if ((!outside_property_arg.isSet() &&
245 !inside_property_arg.isSet()) ||
246 (outside_property_arg.isSet() && inside_property_arg.isSet()))
247 {
248 ERR(
"Specify if the inside or the outside of the selected "
249 "range should be removed.");
250 return EXIT_FAILURE;
251 }
252
253 bool const outside = outside_property_arg.isSet();
255 property_name_arg.getValue(), min_property_arg.getValue(),
256 max_property_arg.getValue(), outside, searcher);
257 }
258 }
259
260 if (xSmallArg.isSet() || xLargeArg.isSet() || ySmallArg.isSet() ||
261 yLargeArg.isSet() || zSmallArg.isSet() || zLargeArg.isSet())
262 {
264 bool aabb_error(false);
265 if (xSmallArg.getValue() >= xLargeArg.getValue())
266 {
267 ERR(
"Minimum x-extent larger than maximum x-extent.");
268 aabb_error = true;
269 }
270 if (ySmallArg.getValue() >= yLargeArg.getValue())
271 {
272 ERR(
"Minimum y-extent larger than maximum y-extent.");
273 aabb_error = true;
274 }
275 if (zSmallArg.getValue() >= zLargeArg.getValue())
276 {
277 ERR(
"Minimum z-extent larger than maximum z-extent.");
278 aabb_error = true;
279 }
280 if (aabb_error)
281 {
282 return EXIT_FAILURE;
283 }
284
285 std::array<MathLib::Point3d, 2> extent(
287 ySmallArg.getValue(),
288 zSmallArg.getValue()}}),
290 {xLargeArg.getValue(), yLargeArg.getValue(),
291 zLargeArg.getValue()}})}});
292 INFO(
"{:d} elements found.",
293 searcher.searchByBoundingBox(
295 invert_bounding_box_arg.getValue()));
296 }
297
298
300 *mesh, searcher.getSearchedElementIDs(), mesh->getName()));
301
302 if (new_mesh == nullptr)
303 {
304 return EXIT_FAILURE;
305 }
306
307
309
310 return EXIT_SUCCESS;
311}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
GITINFOLIB_EXPORT const std::string ogs_version
MeshLib::Mesh * readMeshFromFile(const std::string &file_name, bool const compute_element_neighbors)
int writeMeshToFile(const MeshLib::Mesh &mesh, std::filesystem::path const &file_path, std::set< std::string > variable_output_names)
MeshElemType String2MeshElemType(const std::string &s)
Given a string of the shortened name of the element type, this returns the corresponding MeshElemType...
MeshElemType
Types of mesh elements supported by OpenGeoSys. Values are from VTKCellType enum.
void outputAABB(MeshLib::Mesh const &mesh)
void searchByPropertyValue(std::string const &property_name, std::vector< PROPERTY_TYPE > const &property_values, MeshLib::ElementSearch &searcher)
void searchByPropertyRange(std::string const &property_name, double const &min_value, double const &max_value, bool const &outside, MeshLib::ElementSearch &searcher)